mirror of
https://github.com/ClassiCube/MCGalaxy.git
synced 2025-09-22 12:05:51 -04:00
Completely remove the obsolete MySQL, SQLite3, and Native sqlite backend classes.
This commit is contained in:
parent
65561ad2ea
commit
8bc3fe0675
@ -36,5 +36,11 @@ namespace MCGalaxy.SQL {
|
|||||||
/// <summary> Returns the shared static ParamterisedQuery instance, that is only used
|
/// <summary> Returns the shared static ParamterisedQuery instance, that is only used
|
||||||
/// for sql queries with no parameters. </summary>
|
/// for sql queries with no parameters. </summary>
|
||||||
internal abstract ParameterisedQuery GetStaticParameterised();
|
internal abstract ParameterisedQuery GetStaticParameterised();
|
||||||
|
|
||||||
|
|
||||||
|
// == Higher level functions ==
|
||||||
|
|
||||||
|
/// <summary> Returns whether a table (case sensitive) exists by that name. </summary>
|
||||||
|
public abstract bool TableExists(string table);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,6 +44,12 @@ namespace MCGalaxy.SQL {
|
|||||||
internal override ParameterisedQuery GetStaticParameterised() {
|
internal override ParameterisedQuery GetStaticParameterised() {
|
||||||
return queryInstance;
|
return queryInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool TableExists(string table) {
|
||||||
|
const string syntax = "SELECT * FROM information_schema.tables WHERE table_schema = @1 AND table_name = @0";
|
||||||
|
using (DataTable results = Database.Fill(syntax, table, Server.MySQLDatabaseName))
|
||||||
|
return results.Rows.Count > 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class MySQLBulkTransaction : BulkTransaction {
|
public sealed class MySQLBulkTransaction : BulkTransaction {
|
||||||
@ -69,8 +75,8 @@ namespace MCGalaxy.SQL {
|
|||||||
|
|
||||||
public sealed class MySQLParameterisedQuery : ParameterisedQuery {
|
public sealed class MySQLParameterisedQuery : ParameterisedQuery {
|
||||||
|
|
||||||
public override void Execute(string queryString, bool createDB = false) {
|
public override void Execute(string queryString, string connString, bool createDB = false) {
|
||||||
using (var conn = new MySqlConnection(MySQL.connString)) {
|
using (var conn = new MySqlConnection(connString)) {
|
||||||
conn.Open();
|
conn.Open();
|
||||||
if (!createDB) conn.ChangeDatabase(Server.MySQLDatabaseName);
|
if (!createDB) conn.ChangeDatabase(Server.MySQLDatabaseName);
|
||||||
|
|
||||||
@ -83,8 +89,8 @@ namespace MCGalaxy.SQL {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Fill(string queryString, DataTable toReturn) {
|
public override void Fill(string queryString, string connString, DataTable toReturn) {
|
||||||
using (var conn = new MySqlConnection(MySQL.connString)) {
|
using (var conn = new MySqlConnection(connString)) {
|
||||||
conn.Open();
|
conn.Open();
|
||||||
conn.ChangeDatabase(Server.MySQLDatabaseName);
|
conn.ChangeDatabase(Server.MySQLDatabaseName);
|
||||||
using (MySqlDataAdapter da = new MySqlDataAdapter(queryString, conn)) {
|
using (MySqlDataAdapter da = new MySqlDataAdapter(queryString, conn)) {
|
||||||
|
@ -42,6 +42,12 @@ namespace MCGalaxy.SQL {
|
|||||||
internal override ParameterisedQuery GetStaticParameterised() {
|
internal override ParameterisedQuery GetStaticParameterised() {
|
||||||
return queryInstance;
|
return queryInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool TableExists(string table) {
|
||||||
|
const string syntax = "SELECT name FROM sqlite_master WHERE type='table' AND name=@0";
|
||||||
|
using (DataTable results = Database.Fill(syntax, table))
|
||||||
|
return results.Rows.Count > 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class SQLiteBulkTransaction : BulkTransaction {
|
public sealed class SQLiteBulkTransaction : BulkTransaction {
|
||||||
@ -63,8 +69,8 @@ namespace MCGalaxy.SQL {
|
|||||||
|
|
||||||
public sealed class SQLiteParameterisedQuery : ParameterisedQuery {
|
public sealed class SQLiteParameterisedQuery : ParameterisedQuery {
|
||||||
|
|
||||||
public override void Execute(string query, bool createDB = false) {
|
public override void Execute(string query, string connString, bool createDB = false) {
|
||||||
using (var conn = new SQLiteConnection(SQLite.connString)) {
|
using (var conn = new SQLiteConnection(connString)) {
|
||||||
conn.Open();
|
conn.Open();
|
||||||
using (SQLiteCommand cmd = new SQLiteCommand(query, conn)) {
|
using (SQLiteCommand cmd = new SQLiteCommand(query, conn)) {
|
||||||
foreach (var param in parameters)
|
foreach (var param in parameters)
|
||||||
@ -75,8 +81,8 @@ namespace MCGalaxy.SQL {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Fill(string query, DataTable results) {
|
public override void Fill(string query, string connString, DataTable results) {
|
||||||
using (var conn = new SQLiteConnection(SQLite.connString)) {
|
using (var conn = new SQLiteConnection(connString)) {
|
||||||
conn.Open();
|
conn.Open();
|
||||||
|
|
||||||
using (SQLiteDataAdapter da = new SQLiteDataAdapter(query, conn)) {
|
using (SQLiteDataAdapter da = new SQLiteDataAdapter(query, conn)) {
|
||||||
|
@ -33,17 +33,6 @@ namespace MCGalaxy.SQL {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BulkTransaction CreateNative() {
|
|
||||||
try {
|
|
||||||
return Database.Backend.CreateBulk();
|
|
||||||
// TODO: Use NativeTransaction once I can figure out how to synchronise
|
|
||||||
// System.Data.Sqlite and Native sqlite connection/command disposing.
|
|
||||||
} catch (Exception ex) {
|
|
||||||
Server.ErrorLog(ex);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract IDbCommand CreateCommand(string query);
|
public abstract IDbCommand CreateCommand(string query);
|
||||||
|
|
||||||
public abstract IDataParameter CreateParam(string paramName, DbType type);
|
public abstract IDataParameter CreateParam(string paramName, DbType type);
|
||||||
|
@ -25,9 +25,7 @@ namespace MCGalaxy.SQL {
|
|||||||
public static IDatabaseBackend Backend;
|
public static IDatabaseBackend Backend;
|
||||||
|
|
||||||
public static bool TableExists(string table) {
|
public static bool TableExists(string table) {
|
||||||
string syntax = Server.useMySQL ? MySQL.TableExists : SQLite.TableExists;
|
return Backend.TableExists(table);
|
||||||
using (DataTable results = Fill(syntax, table, Server.MySQLDatabaseName))
|
|
||||||
return results.Rows.Count > 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Obsolete("Use Execute() method instead.")]
|
[Obsolete("Use Execute() method instead.")]
|
||||||
@ -36,11 +34,6 @@ namespace MCGalaxy.SQL {
|
|||||||
Execute(query, queryString, createDB, null);
|
Execute(query, queryString, createDB, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Obsolete("Use Execute() method instead.")]
|
|
||||||
public static void executeQuery(ParameterisedQuery query, string queryString, bool createDB = false) {
|
|
||||||
Execute(query, queryString, createDB, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Execute(string queryString) {
|
public static void Execute(string queryString) {
|
||||||
ParameterisedQuery query = Backend.GetStaticParameterised();
|
ParameterisedQuery query = Backend.GetStaticParameterised();
|
||||||
Execute(query, queryString, false, null);
|
Execute(query, queryString, false, null);
|
||||||
@ -57,11 +50,6 @@ namespace MCGalaxy.SQL {
|
|||||||
return Fill(query, queryString, null);
|
return Fill(query, queryString, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Obsolete("Use Fill() method instead.")]
|
|
||||||
public static DataTable fillData(ParameterisedQuery query, string queryString, bool skipError = false) {
|
|
||||||
return Fill(query, queryString, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static DataTable Fill(string queryString) {
|
public static DataTable Fill(string queryString) {
|
||||||
ParameterisedQuery query = Backend.GetStaticParameterised();
|
ParameterisedQuery query = Backend.GetStaticParameterised();
|
||||||
return Fill(query, queryString, null);
|
return Fill(query, queryString, null);
|
||||||
@ -76,10 +64,12 @@ namespace MCGalaxy.SQL {
|
|||||||
static void Execute(ParameterisedQuery query, string queryString,
|
static void Execute(ParameterisedQuery query, string queryString,
|
||||||
bool createDB, params object[] args) {
|
bool createDB, params object[] args) {
|
||||||
BindParams(query, args);
|
BindParams(query, args);
|
||||||
|
string connString = Backend.ConnectionString;
|
||||||
Exception e = null;
|
Exception e = null;
|
||||||
|
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 10; i++) {
|
||||||
try {
|
try {
|
||||||
query.Execute(queryString, createDB);
|
query.Execute(queryString, connString, createDB);
|
||||||
query.ClearParams();
|
query.ClearParams();
|
||||||
return;
|
return;
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
@ -95,11 +85,13 @@ namespace MCGalaxy.SQL {
|
|||||||
static DataTable Fill(ParameterisedQuery query, string queryString,
|
static DataTable Fill(ParameterisedQuery query, string queryString,
|
||||||
params object[] args) {
|
params object[] args) {
|
||||||
BindParams(query, args);
|
BindParams(query, args);
|
||||||
using (DataTable results = new DataTable("toReturn")) {
|
string connString = Backend.ConnectionString;
|
||||||
Exception e = null;
|
Exception e = null;
|
||||||
|
|
||||||
|
using (DataTable results = new DataTable("toReturn")) {
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 10; i++) {
|
||||||
try {
|
try {
|
||||||
query.Fill(queryString, results);
|
query.Fill(queryString, connString, results);
|
||||||
query.ClearParams();
|
query.ClearParams();
|
||||||
return results;
|
return results;
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
@ -134,16 +126,4 @@ namespace MCGalaxy.SQL {
|
|||||||
query.AddParam(names[i], args[i]);
|
query.AddParam(names[i], args[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class MySQL {
|
|
||||||
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); } }
|
|
||||||
public const string TableExists = "SELECT * FROM information_schema.tables WHERE table_schema = @1 AND table_name = @0";
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class SQLite {
|
|
||||||
static string connStringFormat = "Data Source =" + Server.apppath + "/MCGalaxy.db; Version =3; Pooling ={0}; Max Pool Size =300;";
|
|
||||||
public static string connString { get { return String.Format(connStringFormat, Server.DatabasePooling); } }
|
|
||||||
public const string TableExists = "SELECT name FROM sqlite_master WHERE type='table' AND name=@0";
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -1,49 +0,0 @@
|
|||||||
/*
|
|
||||||
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;
|
|
||||||
|
|
||||||
namespace MCGalaxy.SQL.Native {
|
|
||||||
|
|
||||||
public partial class NativeBulkTransaction : BulkTransaction {
|
|
||||||
|
|
||||||
public NativeBulkTransaction() {
|
|
||||||
connection = new NativeConnection();
|
|
||||||
connection.ConnectionString = SQLite.connString;
|
|
||||||
connection.Open();
|
|
||||||
transaction = connection.BeginTransaction();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override IDbCommand CreateCommand(string query) {
|
|
||||||
IDbCommand cmd = new NativeCommand();
|
|
||||||
cmd.CommandText = query;
|
|
||||||
cmd.Connection = connection;
|
|
||||||
cmd.Transaction = transaction;
|
|
||||||
cmd.Prepare();
|
|
||||||
return cmd;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override IDataParameter CreateParam(string paramName, DbType type) {
|
|
||||||
IDataParameter param = new NativeParameter();
|
|
||||||
param.ParameterName = paramName;
|
|
||||||
param.DbType = type;
|
|
||||||
return param;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,108 +0,0 @@
|
|||||||
/*
|
|
||||||
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.Collections.Generic;
|
|
||||||
using System.Data;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Threading;
|
|
||||||
|
|
||||||
namespace MCGalaxy.SQL.Native {
|
|
||||||
|
|
||||||
unsafe sealed class NativeCommand : IDbCommand {
|
|
||||||
public IntPtr Statement;
|
|
||||||
internal NativeParamsList args = new NativeParamsList();
|
|
||||||
|
|
||||||
public IDbConnection Connection { get; set; }
|
|
||||||
public IDbTransaction Transaction { get; set; }
|
|
||||||
public string CommandText { get; set; }
|
|
||||||
public int CommandTimeout { get; set; }
|
|
||||||
public CommandType CommandType { get; set; }
|
|
||||||
public IDataParameterCollection Parameters { get { return args; } }
|
|
||||||
public UpdateRowSource UpdatedRowSource { get; set; }
|
|
||||||
public IDbDataParameter CreateParameter() { return null; }
|
|
||||||
public void Cancel() { }
|
|
||||||
public IDataReader ExecuteReader() { return ExecuteReader(CommandBehavior.Default); }
|
|
||||||
public IDataReader ExecuteReader(CommandBehavior behavior) { return null; }
|
|
||||||
public object ExecuteScalar() { return null; }
|
|
||||||
|
|
||||||
public void Prepare() {
|
|
||||||
byte[] sql = Interop.MakeUTF8(CommandText);
|
|
||||||
IntPtr db = ((NativeConnection)Connection).DB;
|
|
||||||
IntPtr tail;
|
|
||||||
int code = Interop.sqlite3_prepare_v2(db, sql, sql.Length, out Statement, out tail);
|
|
||||||
if (code > 0) throw new NativeException(code);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int ExecuteNonQuery() {
|
|
||||||
List<NativeParameter> args = this.args.args;
|
|
||||||
for (int i = 0; i < args.Count; i++)
|
|
||||||
BindParam(args[i]);
|
|
||||||
|
|
||||||
int code = Interop.sqlite3_step(Statement);
|
|
||||||
WaitUntilFree(ref code, false);
|
|
||||||
if (code > 0 && code != Interop.Done) throw new NativeException(code);
|
|
||||||
|
|
||||||
code = Interop.sqlite3_reset(Statement);
|
|
||||||
WaitUntilFree(ref code, true);
|
|
||||||
if (code > 0) throw new NativeException(code);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WaitUntilFree(ref int code, bool reset) {
|
|
||||||
DateTime start = DateTime.UtcNow;
|
|
||||||
while (code == Interop.Busy || code == Interop.Locked) {
|
|
||||||
Thread.Sleep(100);
|
|
||||||
TimeSpan delta = DateTime.UtcNow - start;
|
|
||||||
if (delta.TotalSeconds > 30) break;
|
|
||||||
code = reset ? Interop.sqlite3_reset(Statement)
|
|
||||||
: Interop.sqlite3_step(Statement);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose() {
|
|
||||||
int code = Interop.sqlite3_finalize(Statement);
|
|
||||||
if (code > 0) throw new NativeException(code);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BindParam(IDataParameter param) {
|
|
||||||
NativeParameter nParam = (NativeParameter)param;
|
|
||||||
if (nParam.Index == -1) BindIndex(nParam);
|
|
||||||
|
|
||||||
int code = 0;
|
|
||||||
switch (nParam.type) {
|
|
||||||
case DbType.AnsiStringFixedLength:
|
|
||||||
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 = Interop.sqlite3_bind_int(Statement, nParam.Index, nParam.U16Value); break;
|
|
||||||
case DbType.Byte:
|
|
||||||
code = Interop.sqlite3_bind_int(Statement, nParam.Index, nParam.U8Value); break;
|
|
||||||
case DbType.Boolean:
|
|
||||||
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 = Interop.MakeUTF8(nParam.ParameterName);
|
|
||||||
nParam.Index = Interop.sqlite3_bind_parameter_index(Statement, name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,82 +0,0 @@
|
|||||||
/*
|
|
||||||
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 {
|
|
||||||
|
|
||||||
sealed class NativeConnection : IDbConnection {
|
|
||||||
public IntPtr DB;
|
|
||||||
|
|
||||||
public string ConnectionString { get; set; }
|
|
||||||
public int ConnectionTimeout { get { return 0; } }
|
|
||||||
public string Database { get { return ""; } }
|
|
||||||
public ConnectionState State { get { return ConnectionState.Open; } }
|
|
||||||
public IDbTransaction BeginTransaction() { return BeginTransaction(IsolationLevel.Unspecified); }
|
|
||||||
public void ChangeDatabase(string databaseName) { }
|
|
||||||
|
|
||||||
public IDbTransaction BeginTransaction(IsolationLevel il) {
|
|
||||||
return new NativeTransaction(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Close() {
|
|
||||||
IntPtr stmt = IntPtr.Zero;
|
|
||||||
do {
|
|
||||||
stmt = Interop.sqlite3_next_stmt(DB, stmt);
|
|
||||||
if (stmt != IntPtr.Zero) Interop.sqlite3_reset(stmt);
|
|
||||||
} while (stmt != IntPtr.Zero);
|
|
||||||
|
|
||||||
int code = Interop.sqlite3_close(DB);
|
|
||||||
DB = IntPtr.Zero;
|
|
||||||
if (code > 0) throw new NativeException(code);
|
|
||||||
}
|
|
||||||
|
|
||||||
public IDbCommand CreateCommand() {
|
|
||||||
IDbCommand cmd = new NativeCommand();
|
|
||||||
cmd.Connection = this;
|
|
||||||
return cmd;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose() {
|
|
||||||
if (DB == IntPtr.Zero) return;
|
|
||||||
Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
string path;
|
|
||||||
public void Open() {
|
|
||||||
ParseConnectionString();
|
|
||||||
byte[] filename = Interop.MakeUTF8(path);
|
|
||||||
int code = Interop.sqlite3_open_v2(filename, out DB, 0x2, IntPtr.Zero);
|
|
||||||
if (code > 0) throw new NativeException(code);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ParseConnectionString() {
|
|
||||||
string[] args = ConnectionString.Split(';');
|
|
||||||
foreach (string kvp in args) {
|
|
||||||
int sepIndex = kvp.IndexOf('=');
|
|
||||||
if (sepIndex < 0) continue;
|
|
||||||
string key = kvp.Substring(0, sepIndex).Trim();
|
|
||||||
string value = kvp.Substring(sepIndex + 1).Trim();
|
|
||||||
|
|
||||||
if (key == "Data Source") path = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,74 +0,0 @@
|
|||||||
/*
|
|
||||||
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;
|
|
||||||
|
|
||||||
namespace MCGalaxy.SQL.Native {
|
|
||||||
|
|
||||||
sealed class NativeException : Exception {
|
|
||||||
public readonly int ErrorCode;
|
|
||||||
|
|
||||||
public NativeException(int errorCode) {
|
|
||||||
ErrorCode = errorCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string Message { get { return ToString(); } }
|
|
||||||
|
|
||||||
public override string ToString() {
|
|
||||||
byte primaryCode = (byte)ErrorCode;
|
|
||||||
string desc = errors[primaryCode] ?? "SQL error";
|
|
||||||
return desc + " (" + ErrorCode + ")";
|
|
||||||
}
|
|
||||||
|
|
||||||
static string[] errors = new string[256];
|
|
||||||
static NativeException() {
|
|
||||||
errors[0] = "Successful result";
|
|
||||||
errors[1] = "SQL error or missing database";
|
|
||||||
errors[2] = "Internal logic error in SQLite";
|
|
||||||
errors[3] = "Access permission denied";
|
|
||||||
errors[4] = "Callback routine requested an abort";
|
|
||||||
errors[5] = "The database file is locked";
|
|
||||||
errors[6] = "A table in the database is locked";
|
|
||||||
errors[7] = "A malloc() failed";
|
|
||||||
errors[8] = "Attempt to write a readonly database";
|
|
||||||
errors[9] = "Operation terminated by sqlite3_interrupt()";
|
|
||||||
errors[10] = "Some kind of disk I/O error occurred";
|
|
||||||
errors[11] = "The database disk image is malformed";
|
|
||||||
errors[12] = "Unknown opcode in sqlite3_file_control()";
|
|
||||||
errors[13] = "Insertion failed because database is full";
|
|
||||||
errors[14] = "Unable to open the database file";
|
|
||||||
errors[15] = "Database lock protocol error";
|
|
||||||
errors[16] = "Database is empty";
|
|
||||||
errors[17] = "The database schema changed";
|
|
||||||
errors[18] = "String or BLOB exceeds size limit";
|
|
||||||
errors[19] = "Abort due to constraint violation";
|
|
||||||
errors[20] = "Data type mismatch";
|
|
||||||
errors[21] = "Library used incorrectly";
|
|
||||||
errors[22] = "Uses OS features not supported on host";
|
|
||||||
errors[23] = "Authorization denied";
|
|
||||||
errors[24] = "Auxiliary database format error";
|
|
||||||
errors[25] = "2nd parameter to sqlite3_bind out of range";
|
|
||||||
errors[26] = "File opened that is not a database file";
|
|
||||||
errors[27] = "Notifications from sqlite3_log()";
|
|
||||||
errors[28] = "Warnings from sqlite3_log()";
|
|
||||||
errors[100] = "sqlite3_step() has another row ready";
|
|
||||||
errors[101] = "sqlite3_step() has finished executing";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,115 +0,0 @@
|
|||||||
/*
|
|
||||||
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.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Data;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace MCGalaxy.SQL.Native {
|
|
||||||
|
|
||||||
sealed class NativeParamsList : IDataParameterCollection {
|
|
||||||
|
|
||||||
internal List<NativeParameter> args = new List<NativeParameter>();
|
|
||||||
|
|
||||||
public void Clear() {
|
|
||||||
foreach (var param in args)
|
|
||||||
param.Dispose();
|
|
||||||
args.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Boilerplate code for all the interfaces
|
|
||||||
public object this[string parameterName] {
|
|
||||||
get { return args[IndexOf(parameterName)]; }
|
|
||||||
set { args[IndexOf(parameterName)] = (NativeParameter)value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Contains(string parameterName) {
|
|
||||||
return IndexOf(parameterName) >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int IndexOf(string parameterName) {
|
|
||||||
for (int i = 0; i < Count; i++) {
|
|
||||||
if (args[i].ParameterName == parameterName) return i;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void RemoveAt(string parameterName) {
|
|
||||||
int index = IndexOf(parameterName);
|
|
||||||
if (index >= 0) args.RemoveAt(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public bool IsSynchronized { get { return false; } }
|
|
||||||
|
|
||||||
public object SyncRoot { get { return this; } }
|
|
||||||
|
|
||||||
public int Count { get { return args.Count; } }
|
|
||||||
|
|
||||||
public void CopyTo(Array array, int index) { }
|
|
||||||
|
|
||||||
|
|
||||||
public object this[int index] {
|
|
||||||
get { return args[index]; }
|
|
||||||
set { args[index] = (NativeParameter)value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsReadOnly { get { return false; } }
|
|
||||||
|
|
||||||
public bool IsFixedSize { get { return false; } }
|
|
||||||
|
|
||||||
public int Add(object value) { return ((IList)args).Add(value); }
|
|
||||||
|
|
||||||
public bool Contains(object value) { return ((IList)args).Contains(value); }
|
|
||||||
|
|
||||||
public int IndexOf(object value) { return ((IList)args).IndexOf(value); }
|
|
||||||
|
|
||||||
public void Insert(int index, object value) { ((IList)args).Insert(index, value); }
|
|
||||||
|
|
||||||
public void Remove(object value) { ((IList)args).Remove(value); }
|
|
||||||
|
|
||||||
public void RemoveAt(int index) { args.RemoveAt(index); }
|
|
||||||
|
|
||||||
public IEnumerator GetEnumerator() { return args.GetEnumerator(); }
|
|
||||||
|
|
||||||
|
|
||||||
public void AddWithValue(string key, object value) {
|
|
||||||
NativeParameter arg = new NativeParameter();
|
|
||||||
arg.ParameterName = key;
|
|
||||||
Type type = value.GetType();
|
|
||||||
|
|
||||||
if (type == typeof(string)) {
|
|
||||||
arg.SetString((string)value);
|
|
||||||
arg.DbType = DbType.String;
|
|
||||||
} else if (type == typeof(byte)) {
|
|
||||||
arg.U8Value = (byte)value;
|
|
||||||
arg.DbType = DbType.Byte;
|
|
||||||
} 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);
|
|
||||||
}
|
|
||||||
args.Add(arg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,136 +0,0 @@
|
|||||||
/*
|
|
||||||
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.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Data;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Security;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace MCGalaxy.SQL.Native {
|
|
||||||
|
|
||||||
sealed class NativeTransaction : IDbTransaction {
|
|
||||||
public IDbConnection Connection { get; set; }
|
|
||||||
public IsolationLevel IsolationLevel { get { return IsolationLevel.Unspecified; } }
|
|
||||||
|
|
||||||
public NativeTransaction(IDbConnection connection) {
|
|
||||||
Connection = connection;
|
|
||||||
DoCommand("BEGIN");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Commit() { DoCommand("COMMIT"); }
|
|
||||||
public void Rollback() { DoCommand("ROLLBACK"); }
|
|
||||||
public void Dispose() { }
|
|
||||||
|
|
||||||
void DoCommand(string query) {
|
|
||||||
using (IDbCommand cmd = Connection.CreateCommand()) {
|
|
||||||
cmd.CommandText = query;
|
|
||||||
cmd.Prepare();
|
|
||||||
cmd.ExecuteNonQuery();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal unsafe sealed class NativeParameter : IDataParameter {
|
|
||||||
public DbType DbType { get { return type; } set { type = value; } }
|
|
||||||
public ParameterDirection Direction { get; set; }
|
|
||||||
public bool IsNullable { get { return false; } }
|
|
||||||
public string ParameterName { get; set; }
|
|
||||||
public string SourceColumn { get; set; }
|
|
||||||
public DataRowVersion SourceVersion { get; set; }
|
|
||||||
public object Value { get; set; }
|
|
||||||
|
|
||||||
public DbType type;
|
|
||||||
public int Index = -1;
|
|
||||||
// Avoid boxing primitive types
|
|
||||||
public int I32Value;
|
|
||||||
public ushort U16Value;
|
|
||||||
public byte U8Value;
|
|
||||||
public bool BoolValue;
|
|
||||||
public byte* StringPtr;
|
|
||||||
public int StringCount;
|
|
||||||
|
|
||||||
public void SetString(string value) {
|
|
||||||
if ((value.Length + 1) > StringCount) {
|
|
||||||
if (StringCount > 0)
|
|
||||||
Marshal.FreeHGlobal((IntPtr)StringPtr);
|
|
||||||
StringCount = value.Length + 1;
|
|
||||||
StringPtr = (byte*)Marshal.AllocHGlobal(StringCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset all bytes to 0, then replace them.
|
|
||||||
for (int i = 0; i < StringCount; i++)
|
|
||||||
StringPtr[i] = 0;
|
|
||||||
for (int i = 0; i < value.Length; i++)
|
|
||||||
StringPtr[i] = (byte)value[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose() {
|
|
||||||
if (StringCount != 0) return;
|
|
||||||
Marshal.FreeHGlobal((IntPtr)StringPtr);
|
|
||||||
StringCount = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe static class Interop {
|
|
||||||
static Encoding encoding = Encoding.UTF8;
|
|
||||||
const CallingConvention conv = CallingConvention.Cdecl;
|
|
||||||
|
|
||||||
public const int Busy = 5, Locked = 6;
|
|
||||||
public const int RowReady = 100, Done = 101;
|
|
||||||
|
|
||||||
public static byte[] MakeUTF8(string input) {
|
|
||||||
int count = encoding.GetByteCount(input) + 1; // null terminator
|
|
||||||
byte[] chars = new byte[count];
|
|
||||||
encoding.GetBytes(input, 0, input.Length, chars, 0);
|
|
||||||
return chars;
|
|
||||||
}
|
|
||||||
|
|
||||||
[DllImport("sqlite3", CallingConvention = conv), SuppressUnmanagedCodeSecurity]
|
|
||||||
public static extern int sqlite3_open_v2(byte[] filename, out IntPtr db, int flags, IntPtr vfs);
|
|
||||||
|
|
||||||
[DllImport("sqlite3", CallingConvention = conv), SuppressUnmanagedCodeSecurity]
|
|
||||||
public static extern int sqlite3_close(IntPtr db);
|
|
||||||
|
|
||||||
|
|
||||||
[DllImport("sqlite3", CallingConvention = conv), SuppressUnmanagedCodeSecurity]
|
|
||||||
public static extern int sqlite3_bind_int(IntPtr stmt, int index, int value);
|
|
||||||
|
|
||||||
[DllImport("sqlite3", CallingConvention = conv), SuppressUnmanagedCodeSecurity]
|
|
||||||
public static extern int sqlite3_bind_parameter_index(IntPtr stmt, byte[] name);
|
|
||||||
|
|
||||||
[DllImport("sqlite3", CallingConvention = conv), SuppressUnmanagedCodeSecurity]
|
|
||||||
public static extern int sqlite3_bind_text(IntPtr stmt, int index, byte* text, int textLen, IntPtr reserved);
|
|
||||||
|
|
||||||
[DllImport("sqlite3", CallingConvention = conv), SuppressUnmanagedCodeSecurity]
|
|
||||||
public static extern int sqlite3_finalize(IntPtr stmt);
|
|
||||||
|
|
||||||
[DllImport("sqlite3", CallingConvention = conv), SuppressUnmanagedCodeSecurity]
|
|
||||||
public static extern int sqlite3_prepare_v2(IntPtr db, byte[] sql, int nBytes, out IntPtr stmt, out IntPtr sqlTail);
|
|
||||||
|
|
||||||
[DllImport("sqlite3", CallingConvention = conv), SuppressUnmanagedCodeSecurity]
|
|
||||||
public static extern int sqlite3_reset(IntPtr stmt);
|
|
||||||
|
|
||||||
[DllImport("sqlite3", CallingConvention = conv), SuppressUnmanagedCodeSecurity]
|
|
||||||
public static extern int sqlite3_step(IntPtr stmt);
|
|
||||||
|
|
||||||
[DllImport("sqlite3", CallingConvention = conv), SuppressUnmanagedCodeSecurity]
|
|
||||||
public static extern IntPtr sqlite3_next_stmt(IntPtr db, IntPtr stmt);
|
|
||||||
}
|
|
||||||
}
|
|
@ -29,9 +29,9 @@ namespace MCGalaxy.SQL {
|
|||||||
|
|
||||||
public void ClearParams() { parameters.Clear(); }
|
public void ClearParams() { parameters.Clear(); }
|
||||||
|
|
||||||
public abstract void Execute(string query, bool createDB = false);
|
public abstract void Execute(string query, string connString, bool createDB = false);
|
||||||
|
|
||||||
public abstract void Fill(string query, DataTable results);
|
public abstract void Fill(string query, string connString, DataTable results);
|
||||||
|
|
||||||
public static ParameterisedQuery Create() {
|
public static ParameterisedQuery Create() {
|
||||||
return Database.Backend.CreateParameterised();
|
return Database.Backend.CreateParameterised();
|
||||||
|
@ -19,7 +19,6 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Data;
|
using System.Data;
|
||||||
using MCGalaxy.SQL;
|
using MCGalaxy.SQL;
|
||||||
using MCGalaxy.SQL.Native;
|
|
||||||
|
|
||||||
namespace MCGalaxy {
|
namespace MCGalaxy {
|
||||||
public static class LevelDB {
|
public static class LevelDB {
|
||||||
@ -32,7 +31,7 @@ namespace MCGalaxy {
|
|||||||
|
|
||||||
fixed (char* ptr = date) {
|
fixed (char* ptr = date) {
|
||||||
ptr[4] = '-'; ptr[7] = '-'; ptr[10] = ' '; ptr[13] = ':'; ptr[16] = ':';
|
ptr[4] = '-'; ptr[7] = '-'; ptr[10] = ' '; ptr[13] = ':'; ptr[16] = ':';
|
||||||
using (BulkTransaction bulk = BulkTransaction.CreateNative())
|
using (BulkTransaction bulk = BulkTransaction.Create())
|
||||||
DoSaveChanges(tempCache, ptr, lvl, date, bulk);
|
DoSaveChanges(tempCache, ptr, lvl, date, bulk);
|
||||||
}
|
}
|
||||||
tempCache.Clear();
|
tempCache.Clear();
|
||||||
@ -56,7 +55,6 @@ namespace MCGalaxy {
|
|||||||
IDataParameter zP = transaction.CreateParam("@Z", DbType.UInt16); cmd.Parameters.Add(zP);
|
IDataParameter zP = transaction.CreateParam("@Z", DbType.UInt16); cmd.Parameters.Add(zP);
|
||||||
IDataParameter tileP = transaction.CreateParam("@Tile", DbType.Byte); cmd.Parameters.Add(tileP);
|
IDataParameter tileP = transaction.CreateParam("@Tile", DbType.Byte); cmd.Parameters.Add(tileP);
|
||||||
IDataParameter delP = transaction.CreateParam("@Del", DbType.Boolean); cmd.Parameters.Add(delP);
|
IDataParameter delP = transaction.CreateParam("@Del", DbType.Boolean); cmd.Parameters.Add(delP);
|
||||||
bool isNative = transaction is NativeBulkTransaction;
|
|
||||||
|
|
||||||
for (int i = 0; i < tempCache.Count; i++) {
|
for (int i = 0; i < tempCache.Count; i++) {
|
||||||
Level.BlockPos bP = tempCache[i];
|
Level.BlockPos bP = tempCache[i];
|
||||||
@ -65,22 +63,11 @@ namespace MCGalaxy {
|
|||||||
MakeInt(time.Year, 4, 0, ptr); MakeInt(time.Month, 2, 5, ptr); MakeInt(time.Day, 2, 8, ptr);
|
MakeInt(time.Year, 4, 0, ptr); MakeInt(time.Month, 2, 5, ptr); MakeInt(time.Day, 2, 8, ptr);
|
||||||
MakeInt(time.Hour, 2, 11, ptr); MakeInt(time.Minute, 2, 14, ptr); MakeInt(time.Second, 2, 17, ptr);
|
MakeInt(time.Hour, 2, 11, ptr); MakeInt(time.Minute, 2, 14, ptr); MakeInt(time.Second, 2, 17, ptr);
|
||||||
|
|
||||||
// For NativeParameter, we make the optimisation of avoiding boxing primitive types.
|
|
||||||
if (!isNative) {
|
|
||||||
nameP.Value = bP.name;
|
nameP.Value = bP.name;
|
||||||
timeP.Value = date;
|
timeP.Value = date;
|
||||||
xP.Value = x; yP.Value = y; zP.Value = z;
|
xP.Value = x; yP.Value = y; zP.Value = z;
|
||||||
tileP.Value = (bP.flags & 2) != 0 ? Block.custom_block : bP.rawBlock;
|
tileP.Value = (bP.flags & 2) != 0 ? Block.custom_block : bP.rawBlock;
|
||||||
delP.Value = (bP.flags & 1) != 0;
|
delP.Value = (bP.flags & 1) != 0;
|
||||||
} else {
|
|
||||||
((NativeParameter)nameP).SetString(bP.name);
|
|
||||||
((NativeParameter)timeP).SetString(date);
|
|
||||||
((NativeParameter)xP).U16Value = x;
|
|
||||||
((NativeParameter)yP).U16Value = y;
|
|
||||||
((NativeParameter)zP).U16Value = z;
|
|
||||||
((NativeParameter)tileP).U8Value = (bP.flags & 2) != 0 ? Block.custom_block : bP.rawBlock;
|
|
||||||
((NativeParameter)delP).BoolValue = (bP.flags & 1) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!BulkTransaction.Execute(template, cmd)) {
|
if (!BulkTransaction.Execute(template, cmd)) {
|
||||||
cmd.Dispose();
|
cmd.Dispose();
|
||||||
|
@ -409,13 +409,7 @@
|
|||||||
<Compile Include="Database\Backends\SQLiteBackend.cs" />
|
<Compile Include="Database\Backends\SQLiteBackend.cs" />
|
||||||
<Compile Include="Database\Backends\MySQLBackend.cs" />
|
<Compile Include="Database\Backends\MySQLBackend.cs" />
|
||||||
<Compile Include="Database\BlockDB.cs" />
|
<Compile Include="Database\BlockDB.cs" />
|
||||||
<Compile Include="Database\Native\NativeParamsList.cs" />
|
|
||||||
<Compile Include="Database\ParameterisedQuery.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="Drawing\Brushes\Brush.cs" />
|
<Compile Include="Drawing\Brushes\Brush.cs" />
|
||||||
<Compile Include="Drawing\Brushes\CloudyBrush.cs" />
|
<Compile Include="Drawing\Brushes\CloudyBrush.cs" />
|
||||||
<Compile Include="Drawing\Brushes\PasteBrush.cs" />
|
<Compile Include="Drawing\Brushes\PasteBrush.cs" />
|
||||||
@ -700,7 +694,6 @@
|
|||||||
<Folder Include="Commands\Scripting" />
|
<Folder Include="Commands\Scripting" />
|
||||||
<Folder Include="Commands\World" />
|
<Folder Include="Commands\World" />
|
||||||
<Folder Include="Commands\other" />
|
<Folder Include="Commands\other" />
|
||||||
<Folder Include="Database\Native" />
|
|
||||||
<Folder Include="Database\Backends" />
|
<Folder Include="Database\Backends" />
|
||||||
<Folder Include="Drawing\DrawOps" />
|
<Folder Include="Drawing\DrawOps" />
|
||||||
<Folder Include="Drawing\Brushes" />
|
<Folder Include="Drawing\Brushes" />
|
||||||
|
Loading…
x
Reference in New Issue
Block a user