More work on native sqlite backend.

This commit is contained in:
UnknownShadow200 2016-03-25 19:06:34 +11:00
parent 67dabbf819
commit 18ba121b88
5 changed files with 171 additions and 32 deletions

View File

@ -48,7 +48,7 @@ namespace MCGalaxy.SQL.Native {
}
public override IDbCommand CreateCommand(string query) {
IDbCommand cmd = new NativeSQLiteCommand();
IDbCommand cmd = new NativeCommand();
cmd.CommandText = query;
cmd.Connection = connection;
cmd.Transaction = transaction;
@ -61,11 +61,5 @@ namespace MCGalaxy.SQL.Native {
param.DbType = type;
return param;
}
[DllImport("sqlite3.dll")]
static extern int sqlite3_open_v2(byte[] filename, out IntPtr db, int flags, IntPtr vfs);
[DllImport("sqlite3.dll")]
static extern int sqlite3_close_v2(IntPtr db);
}
}

View File

@ -16,22 +16,23 @@
permissions and limitations under the Licenses.
*/
using System;
using System.Collections.Generic;
using System.Data;
using System.Runtime.InteropServices;
namespace MCGalaxy.SQL.Native {
sealed class NativeSQLiteCommand : IDbCommand {
IntPtr statement;
sealed class NativeCommand : IDbCommand {
public IntPtr Statement;
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; private 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); }
@ -39,21 +40,70 @@ namespace MCGalaxy.SQL.Native {
public object ExecuteScalar() { return null; }
public void Prepare() {
byte[] sql = NativeUtils.MakeUTF8(CommandText);
IntPtr db = ((NativeConnection)Connection).DB;
IntPtr tail;
int code = sqlite3_prepare_v2(db, sql, sql.Length, out Statement, out tail);
if (code > 0) throw new NativeException(code);
}
public int ExecuteNonQuery() {
int code = sqlite3_step(statement);
foreach (IDataParameter param in args)
BindParam(param);
int code = sqlite3_step(Statement);
if (code > 0) throw new NativeException(code);
code = sqlite3_reset(statement);
code = sqlite3_reset(Statement);
if (code > 0) throw new NativeException(code);
return 0;
}
public void Dispose() {
int code = sqlite3_finalize(statement);
int code = sqlite3_finalize(Statement);
if (code > 0) throw new NativeException(code);
}
void BindParam(IDataParameter param) {
NativeParameter nParam = (NativeParameter)param;
if (nParam.Index == -1) BindIndex(nParam);
DbType type = param.DbType;
int code = 0;
switch (type) {
case DbType.AnsiStringFixedLength:
byte[] data = NativeUtils.MakeUTF8((string)nParam.Value);
code = sqlite3_bind_text(Statement, nParam.Index, data, data.Length - 1, IntPtr.Zero);
break;
case DbType.UInt16:
ushort value_u16 = (ushort)nParam.Value;
code = sqlite3_bind_int(Statement, nParam.Index, value_u16);
break;
case DbType.Byte:
byte value_u8 = (byte)nParam.Value;
code = sqlite3_bind_int(Statement, nParam.Index, value_u8);
break;
case DbType.Boolean:
bool value_bool = (bool)nParam.Value;
code = sqlite3_bind_int(Statement, nParam.Index, value_bool ? 1 : 0);
break;
}
if (code > 0) throw new NativeException(code);
}
void BindIndex(NativeParameter nParam) {
byte[] name = NativeUtils.MakeUTF8(nParam.ParameterName);
nParam.Index = sqlite3_bind_parameter_index(Statement, name);
}
[DllImport("sqlite3.dll")]
static extern int sqlite3_bind_int(IntPtr stmt, int index, int value);
[DllImport("sqlite3.dll")]
static extern int sqlite3_bind_parameter_index(IntPtr stmt, byte[] name);
[DllImport("sqlite3.dll")]
static extern int sqlite3_bind_text(IntPtr stmt, int index, byte[] text, int textLen, IntPtr reserved);
[DllImport("sqlite3.dll")]
static extern int sqlite3_finalize(IntPtr stmt);

View File

@ -0,0 +1,69 @@
/*
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 null;
}
public void Close() {
int code = sqlite3_close_v2(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();
}
public void Open() {
string[] args = ConnectionString.Split(';');
byte[] filename = NativeUtils.MakeUTF8(args[0]);
int code = sqlite3_open_v2(filename, out DB, 0, IntPtr.Zero);
if (code > 0) throw new NativeException(code);
}
[DllImport("sqlite3.dll")]
static extern int sqlite3_open_v2(byte[] filename, out IntPtr db, int flags, IntPtr vfs);
[DllImport("sqlite3.dll")]
static extern int sqlite3_close_v2(IntPtr db);
}
}

View File

@ -16,32 +16,32 @@
permissions and limitations under the Licenses.
*/
using System;
using System.Collections.Generic;
using System.Data;
using System.Text;
namespace MCGalaxy.SQL.Native {
sealed class NativeConnection : IDbConnection {
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 IDbTransaction BeginTransaction(IsolationLevel il) { return null; }
public void Close() { }
public void ChangeDatabase(string databaseName) { }
public IDbCommand CreateCommand() { return null; }
public void Open() { }
public void Dispose() { }
}
sealed class NativeTransaction : IDbTransaction {
public IDbConnection Connection { get; set; }
public IsolationLevel IsolationLevel { get { return IsolationLevel.Unspecified; } }
public void Commit() { }
public void Rollback() { }
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();
}
}
}
sealed class NativeParameter : IDataParameter {
@ -52,6 +52,31 @@ namespace MCGalaxy.SQL.Native {
public string SourceColumn { get; set; }
public DataRowVersion SourceVersion { get; set; }
public object Value { get; set; }
public int Index = -1;
}
sealed class NativeParamsList : List<IDataParameter>, IDataParameterCollection {
public object this[string parameterName] {
get { return this[IndexOf(parameterName)]; }
set { this[IndexOf(parameterName)] = (IDbDataParameter)value; }
}
public bool Contains(string parameterName) {
return IndexOf(parameterName) >= 0;
}
public int IndexOf(string parameterName) {
for (int i = 0; i < Count; i++) {
if (this[i].ParameterName == parameterName) return i;
}
return -1;
}
public void RemoveAt(string parameterName) {
int index = IndexOf(parameterName);
if (index >= 0) RemoveAt(index);
}
}
static class NativeUtils {

View File

@ -393,6 +393,7 @@
<Compile Include="Commands\World\CmdUnload.cs" />
<Compile Include="Database\DatabaseParameterisedQuery.cs" />
<Compile Include="Database\MySQLParameterisedQuery.cs" />
<Compile Include="Database\Native\NativeConnection.cs" />
<Compile Include="Database\Native\Utils.cs" />
<Compile Include="Database\Native\BulkNativeTransaction.cs" />
<Compile Include="Database\Native\NativeCommand.cs" />