mirror of
https://github.com/ClassiCube/MCGalaxy.git
synced 2025-09-24 05:03:34 -04:00
Move SQLite backend to new interfaces
This commit is contained in:
parent
81b1617ba1
commit
bad7d3443e
@ -35,18 +35,10 @@ namespace MCGalaxy.SQL
|
|||||||
public override bool MultipleSchema { get { return false; } }
|
public override bool MultipleSchema { get { return false; } }
|
||||||
public override string EngineName { get { return "SQLite"; } }
|
public override string EngineName { get { return "SQLite"; } }
|
||||||
|
|
||||||
internal override IDbConnection CreateConnection() {
|
public override ISqlConnection CreateConnection() {
|
||||||
return new MCGSQLiteConnection();
|
return new MCGSQLiteConnection();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override IDbCommand CreateCommand(string sql, IDbConnection conn) {
|
|
||||||
return new SQLiteCommand(sql, (SQLiteConnection)conn);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal override IDbDataParameter CreateParameter() {
|
|
||||||
return new SQLiteParameter();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public override void LoadDependencies() {
|
public override void LoadDependencies() {
|
||||||
// on macOS/Linux, use the system provided sqlite3 native library
|
// on macOS/Linux, use the system provided sqlite3 native library
|
||||||
@ -67,7 +59,7 @@ namespace MCGalaxy.SQL
|
|||||||
|
|
||||||
public override void CreateDatabase() { }
|
public override void CreateDatabase() { }
|
||||||
|
|
||||||
public override string RawGetDateTime(IDataRecord record, int col) {
|
public override string RawGetDateTime(ISqlRecord record, int col) {
|
||||||
return record.GetString(col); // reader.GetDateTime is extremely slow so avoid it
|
return record.GetString(col); // reader.GetDateTime is extremely slow so avoid it
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,7 +138,8 @@ namespace MCGalaxy.SQL
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class MCGSQLiteConnection : SQLiteConnection {
|
sealed class MCGSQLiteConnection : SQLiteConnection
|
||||||
|
{
|
||||||
protected override bool ConnectionPooling { get { return Server.Config.DatabasePooling; } }
|
protected override bool ConnectionPooling { get { return Server.Config.DatabasePooling; } }
|
||||||
protected override string DBPath { get { return "MCGalaxy.db"; } }
|
protected override string DBPath { get { return "MCGalaxy.db"; } }
|
||||||
}
|
}
|
||||||
|
@ -5,9 +5,7 @@
|
|||||||
* Released to the public domain, use at your own risk!
|
* Released to the public domain, use at your own risk!
|
||||||
********************************************************/
|
********************************************************/
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Data;
|
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Security;
|
using System.Security;
|
||||||
@ -15,10 +13,20 @@ using System.Text;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using SQLiteErrorCode = System.Int32;
|
using SQLiteErrorCode = System.Int32;
|
||||||
|
|
||||||
namespace MCGalaxy.SQL {
|
namespace MCGalaxy.SQL
|
||||||
|
{
|
||||||
|
enum SqlType
|
||||||
|
{
|
||||||
|
Single, Double, Decimal,
|
||||||
|
SByte, Int16, Int32, Int64,
|
||||||
|
Byte, UInt16, UInt32, UInt64,
|
||||||
|
Boolean, DateTime,
|
||||||
|
Binary, String, Object,
|
||||||
|
}
|
||||||
|
|
||||||
[SuppressUnmanagedCodeSecurity]
|
[SuppressUnmanagedCodeSecurity]
|
||||||
internal static class Interop {
|
static class Interop
|
||||||
|
{
|
||||||
const string lib = "sqlite3";
|
const string lib = "sqlite3";
|
||||||
|
|
||||||
[DllImport(lib, CallingConvention = CallingConvention.Cdecl)]
|
[DllImport(lib, CallingConvention = CallingConvention.Cdecl)]
|
||||||
@ -100,28 +108,21 @@ namespace MCGalaxy.SQL {
|
|||||||
internal static extern IntPtr sqlite3_errstr(SQLiteErrorCode rc); /* 3.7.15+ */
|
internal static extern IntPtr sqlite3_errstr(SQLiteErrorCode rc); /* 3.7.15+ */
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract class SQLiteConnection : IDbConnection {
|
public abstract class SQLiteConnection : ISqlConnection
|
||||||
ConnectionState state = ConnectionState.Closed;
|
{
|
||||||
internal int _transactionLevel;
|
internal int _transactionLevel;
|
||||||
IntPtr handle;
|
public IntPtr handle;
|
||||||
|
|
||||||
protected abstract bool ConnectionPooling { get; }
|
protected abstract bool ConnectionPooling { get; }
|
||||||
protected abstract string DBPath { get; }
|
protected abstract string DBPath { get; }
|
||||||
|
|
||||||
public IDbTransaction BeginTransaction(IsolationLevel isolationLevel) {
|
public override ISqlTransaction BeginTransaction() {
|
||||||
return new SQLiteTransaction(this);
|
return new SQLiteTransaction(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IDbTransaction BeginTransaction() {
|
public override void ChangeDatabase(string databaseName) { }
|
||||||
return new SQLiteTransaction(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ChangeDatabase(string databaseName) { }
|
public override ISqlCommand CreateCommand(string sql) { return new SQLiteCommand(sql, this); }
|
||||||
public int ConnectionTimeout { get { return SQLiteConvert.Timeout; } }
|
|
||||||
public string ConnectionString { get { return ""; } set { } }
|
|
||||||
|
|
||||||
public IDbCommand CreateCommand() { return new SQLiteCommand(this); }
|
|
||||||
public string Database { get { return "main"; } }
|
|
||||||
|
|
||||||
public long LastInsertRowId {
|
public long LastInsertRowId {
|
||||||
get {
|
get {
|
||||||
@ -144,8 +145,6 @@ namespace MCGalaxy.SQL {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConnectionState State { get { return state; } }
|
|
||||||
|
|
||||||
public SQLiteErrorCode ResultCode() {
|
public SQLiteErrorCode ResultCode() {
|
||||||
if (handle == IntPtr.Zero) throw new InvalidOperationException("Database connection closed");
|
if (handle == IntPtr.Zero) throw new InvalidOperationException("Database connection closed");
|
||||||
return Interop.sqlite3_errcode(handle);
|
return Interop.sqlite3_errcode(handle);
|
||||||
@ -182,9 +181,8 @@ namespace MCGalaxy.SQL {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Open() {
|
public override void Open() {
|
||||||
if (state != ConnectionState.Closed) throw new InvalidOperationException();
|
if (handle != IntPtr.Zero) throw new InvalidOperationException();
|
||||||
Close();
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (ConnectionPooling) handle = RemoveFromPool();
|
if (ConnectionPooling) handle = RemoveFromPool();
|
||||||
@ -200,7 +198,6 @@ namespace MCGalaxy.SQL {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SetTimeout(0);
|
SetTimeout(0);
|
||||||
state = ConnectionState.Open;
|
|
||||||
} catch (SQLiteException) {
|
} catch (SQLiteException) {
|
||||||
Close();
|
Close();
|
||||||
throw;
|
throw;
|
||||||
@ -216,10 +213,8 @@ namespace MCGalaxy.SQL {
|
|||||||
internal static void Check(SQLiteConnection connection) {
|
internal static void Check(SQLiteConnection connection) {
|
||||||
if (connection == null)
|
if (connection == null)
|
||||||
throw new ArgumentNullException("connection");
|
throw new ArgumentNullException("connection");
|
||||||
if (connection.state != ConnectionState.Open)
|
|
||||||
throw new InvalidOperationException("The connection is not open.");
|
|
||||||
if (connection.handle == IntPtr.Zero)
|
if (connection.handle == IntPtr.Zero)
|
||||||
throw new InvalidOperationException("The connection handle is invalid.");
|
throw new InvalidOperationException("The connection is not open.");
|
||||||
}
|
}
|
||||||
|
|
||||||
internal bool Reset(bool canThrow) {
|
internal bool Reset(bool canThrow) {
|
||||||
@ -242,8 +237,8 @@ namespace MCGalaxy.SQL {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose() { Close(false); }
|
public override void Dispose() { Close(false); }
|
||||||
public void Close() { Close(true); }
|
public override void Close() { Close(true); }
|
||||||
|
|
||||||
void Close(bool canThrow) {
|
void Close(bool canThrow) {
|
||||||
if (handle == IntPtr.Zero) return;
|
if (handle == IntPtr.Zero) return;
|
||||||
@ -289,16 +284,17 @@ namespace MCGalaxy.SQL {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class SQLiteCommand : IDbCommand {
|
public sealed class SQLiteCommand : ISqlCommand
|
||||||
string strCmdText, strRemaining;
|
{
|
||||||
SQLiteConnection conn;
|
string sqlCmd;
|
||||||
SQLiteParameterCollection parameters = new SQLiteParameterCollection();
|
internal SQLiteConnection conn;
|
||||||
SQLiteStatement stmt;
|
SQLiteStatement stmt;
|
||||||
|
List<string> param_names = new List<string>();
|
||||||
|
List<object> param_values = new List<object>();
|
||||||
|
|
||||||
public SQLiteCommand(SQLiteConnection connection) : this(null, connection) { }
|
public SQLiteCommand(string sql, SQLiteConnection connection) {
|
||||||
public SQLiteCommand(string commandText, SQLiteConnection connection) {
|
sqlCmd = sql;
|
||||||
if (commandText != null) CommandText = commandText;
|
conn = connection;
|
||||||
if (connection != null) Connection = connection;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DisposeStatement() {
|
void DisposeStatement() {
|
||||||
@ -306,78 +302,61 @@ namespace MCGalaxy.SQL {
|
|||||||
stmt = null;
|
stmt = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose() {
|
public override void Dispose() {
|
||||||
conn = null;
|
conn = null;
|
||||||
parameters.Clear();
|
param_names.Clear();
|
||||||
strCmdText = null;
|
param_values.Clear();
|
||||||
strRemaining = null;
|
sqlCmd = null;
|
||||||
DisposeStatement();
|
DisposeStatement();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal SQLiteStatement NextStatement() {
|
internal SQLiteStatement NextStatement() {
|
||||||
if (stmt != null) DisposeStatement();
|
if (stmt != null) DisposeStatement();
|
||||||
if (String.IsNullOrEmpty(strRemaining)) return null;
|
if (String.IsNullOrEmpty(sqlCmd)) return null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
stmt = conn.Prepare(strRemaining, ref strRemaining);
|
stmt = conn.Prepare(sqlCmd, ref sqlCmd);
|
||||||
} catch (Exception) {
|
} catch (Exception) {
|
||||||
DisposeStatement();
|
DisposeStatement();
|
||||||
// Cannot continue on, so set the remaining text to null.
|
// Cannot continue on, so set the remaining text to null.
|
||||||
strRemaining = null;
|
sqlCmd = null;
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stmt != null) stmt.BindAll(parameters);
|
if (stmt != null) stmt.BindAll(param_names, param_values);
|
||||||
return stmt;
|
return stmt;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Cancel() { }
|
public override void Prepare() { }
|
||||||
public string CommandText {
|
|
||||||
get { return strCmdText; }
|
public override void ClearParameters() {
|
||||||
set { strCmdText = value; strRemaining = value; }
|
param_names.Clear();
|
||||||
|
param_values.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int CommandTimeout {
|
public override void AddParameter(string name, object value) {
|
||||||
get { return SQLiteConvert.Timeout; } set { }
|
param_names.Add(name);
|
||||||
|
param_values.Add(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IDbConnection Connection {
|
public override ISqlReader ExecuteReader() {
|
||||||
get { return conn; } set { conn = (SQLiteConnection)value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public CommandType CommandType { get { return CommandType.Text; } set { } }
|
|
||||||
public IDbDataParameter CreateParameter() { return new SQLiteParameter(); }
|
|
||||||
public IDataParameterCollection Parameters { get { return parameters; } }
|
|
||||||
public IDbTransaction Transaction { get { return null; } set { } }
|
|
||||||
|
|
||||||
public IDataReader ExecuteReader(CommandBehavior behavior) {
|
|
||||||
SQLiteConnection.Check(conn);
|
SQLiteConnection.Check(conn);
|
||||||
return new SQLiteDataReader(this);
|
|
||||||
}
|
|
||||||
public IDataReader ExecuteReader() { return ExecuteReader(0); }
|
|
||||||
|
|
||||||
public int ExecuteNonQuery() {
|
SQLiteDataReader reader = new SQLiteDataReader(this);
|
||||||
using (IDataReader reader = ExecuteReader()) {
|
reader.NextResult();
|
||||||
while (reader.NextResult()) { }
|
return reader;
|
||||||
return reader.RecordsAffected;
|
}
|
||||||
|
|
||||||
|
public override int ExecuteNonQuery() {
|
||||||
|
using (ISqlReader reader = ExecuteReader()) {
|
||||||
|
while (reader.Read()) { }
|
||||||
|
return reader.RowsAffected;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public object ExecuteScalar() {
|
|
||||||
using (IDataReader reader = ExecuteReader()) {
|
|
||||||
if (reader.Read()) return reader[0];
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Prepare() { }
|
|
||||||
|
|
||||||
public UpdateRowSource UpdatedRowSource {
|
|
||||||
get { return UpdateRowSource.None; } set { }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static class SQLiteConvert {
|
static class SQLiteConvert
|
||||||
|
{
|
||||||
static string[] _datetimeFormats = new string[] {
|
static string[] _datetimeFormats = new string[] {
|
||||||
"yyyy-MM-dd HH:mm:ss.FFFFFFFK", /* NOTE: UTC default (0). */
|
"yyyy-MM-dd HH:mm:ss.FFFFFFFK", /* NOTE: UTC default (0). */
|
||||||
"yyyy-MM-dd HH:mm:ssK",
|
"yyyy-MM-dd HH:mm:ssK",
|
||||||
@ -450,80 +429,65 @@ namespace MCGalaxy.SQL {
|
|||||||
typeof(object), // Null (5)
|
typeof(object), // Null (5)
|
||||||
};
|
};
|
||||||
|
|
||||||
internal static DbType TypeToDbType(Type typ) {
|
internal static SqlType TypeToDbType(Type typ) {
|
||||||
TypeCode tc = Type.GetTypeCode(typ);
|
TypeCode tc = Type.GetTypeCode(typ);
|
||||||
if (tc == TypeCode.Object) {
|
if (tc == TypeCode.Object) {
|
||||||
if (typ == typeof(byte[])) return DbType.Binary;
|
if (typ == typeof(byte[])) return SqlType.Binary;
|
||||||
return DbType.String;
|
return SqlType.String;
|
||||||
}
|
}
|
||||||
return type_to_dbtype[(int)tc];
|
return type_to_dbtype[(int)tc];
|
||||||
}
|
}
|
||||||
|
|
||||||
static DbType[] type_to_dbtype = {
|
static SqlType[] type_to_dbtype = {
|
||||||
DbType.Object, // Empty (0)
|
SqlType.Object, // Empty (0)
|
||||||
DbType.Binary, // Object (1)
|
SqlType.Binary, // Object (1)
|
||||||
DbType.Object, // DBNull (2)
|
SqlType.Object, // DBNull (2)
|
||||||
DbType.Boolean, // Boolean (3)
|
SqlType.Boolean, // Boolean (3)
|
||||||
DbType.SByte, // Char (4)
|
SqlType.SByte, // Char (4)
|
||||||
DbType.SByte, // SByte (5)
|
SqlType.SByte, // SByte (5)
|
||||||
DbType.Byte, // Byte (6)
|
SqlType.Byte, // Byte (6)
|
||||||
DbType.Int16, // Int16 (7)
|
SqlType.Int16, // Int16 (7)
|
||||||
DbType.UInt16, // UInt16 (8)
|
SqlType.UInt16, // UInt16 (8)
|
||||||
DbType.Int32, // Int32 (9)
|
SqlType.Int32, // Int32 (9)
|
||||||
DbType.UInt32, // UInt32 (10)
|
SqlType.UInt32, // UInt32 (10)
|
||||||
DbType.Int64, // Int64 (11)
|
SqlType.Int64, // Int64 (11)
|
||||||
DbType.UInt64, // UInt64 (12)
|
SqlType.UInt64, // UInt64 (12)
|
||||||
DbType.Single, // Single (13)
|
SqlType.Single, // Single (13)
|
||||||
DbType.Double, // Double (14)
|
SqlType.Double, // Double (14)
|
||||||
DbType.Decimal, // Decimal (15)
|
SqlType.Decimal, // Decimal (15)
|
||||||
DbType.DateTime, // DateTime (16)
|
SqlType.DateTime, // DateTime (16)
|
||||||
DbType.Object, // ?? (17)
|
SqlType.Object, // ?? (17)
|
||||||
DbType.String // String (18)
|
SqlType.String // String (18)
|
||||||
};
|
};
|
||||||
|
|
||||||
internal static Type[] dbtype_to_type = {
|
internal static Type[] sqltype_to_type = {
|
||||||
typeof(string), // AnsiString (0)
|
typeof(float), typeof(double), typeof(decimal),
|
||||||
typeof(byte[]), // Binary (1)
|
typeof(sbyte), typeof(Int16), typeof(Int32), typeof(Int64),
|
||||||
typeof(byte), // Byte (2)
|
typeof(byte), typeof(UInt16), typeof(UInt32), typeof(UInt64),
|
||||||
typeof(bool), // Boolean (3)
|
typeof(bool), typeof(DateTime),
|
||||||
typeof(decimal), // Currency (4)
|
typeof(byte[]), typeof(string), typeof(object)
|
||||||
typeof(DateTime), // Date (5)
|
|
||||||
typeof(DateTime), // DateTime (6)
|
|
||||||
typeof(decimal), // Decimal (7)
|
|
||||||
typeof(double), // Double (8)
|
|
||||||
typeof(Guid), // Guid (9)
|
|
||||||
typeof(Int16), // Int16 (10)
|
|
||||||
typeof(Int32), // Int32 (11)
|
|
||||||
typeof(Int64), // Int64 (12)
|
|
||||||
typeof(object), // Object (13)
|
|
||||||
typeof(sbyte), // SByte (14)
|
|
||||||
typeof(float), // Single (15)
|
|
||||||
typeof(string), // String (16)
|
|
||||||
typeof(DateTime), // Time (17)
|
|
||||||
typeof(UInt16), // UInt16 (18)
|
|
||||||
typeof(UInt32), // UInt32 (19)
|
|
||||||
typeof(UInt64), // UInt64 (20)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool TryParseDbType(string typeName, out DbType type) {
|
static bool TryParseDbType(string typeName, out SqlType type) {
|
||||||
string[] names = all_names;
|
string[] names = all_names;
|
||||||
for (int i = 0; i < names.Length; i++) {
|
for (int i = 0; i < names.Length; i++)
|
||||||
|
{
|
||||||
if (!typeName.Equals(names[i], StringComparison.OrdinalIgnoreCase)) continue;
|
if (!typeName.Equals(names[i], StringComparison.OrdinalIgnoreCase)) continue;
|
||||||
type = all_types[i]; return true;
|
type = all_types[i]; return true;
|
||||||
}
|
}
|
||||||
type = 0; return false;
|
type = 0; return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static DbType TypeNameToDbType(string typeName) {
|
internal static SqlType TypeNameToDbType(string typeName) {
|
||||||
if (typeName == null) return DbType.Object;
|
if (typeName == null) return SqlType.Object;
|
||||||
|
|
||||||
DbType value;
|
SqlType value;
|
||||||
if (TryParseDbType(typeName, out value)) return value;
|
if (TryParseDbType(typeName, out value)) return value;
|
||||||
|
|
||||||
int i = typeName.IndexOf('(');
|
int i = typeName.IndexOf('(');
|
||||||
if (i > 0 && TryParseDbType(typeName.Substring(0, i).TrimEnd(), out value)) return value;
|
if (i > 0 && TryParseDbType(typeName.Substring(0, i).TrimEnd(), out value)) return value;
|
||||||
|
|
||||||
return DbType.Object;
|
return SqlType.Object;
|
||||||
}
|
}
|
||||||
|
|
||||||
static string[] all_names = new string[] {
|
static string[] all_names = new string[] {
|
||||||
@ -541,23 +505,24 @@ namespace MCGalaxy.SQL {
|
|||||||
"VARCHAR",
|
"VARCHAR",
|
||||||
};
|
};
|
||||||
|
|
||||||
static DbType[] all_types = new DbType[] {
|
static SqlType[] all_types = new SqlType[] {
|
||||||
DbType.Int64, DbType.UInt64, DbType.Binary, DbType.Binary,
|
SqlType.Int64, SqlType.UInt64, SqlType.Binary, SqlType.Binary,
|
||||||
DbType.Boolean, DbType.Boolean, DbType.String, DbType.DateTime,
|
SqlType.Boolean, SqlType.Boolean, SqlType.String, SqlType.DateTime,
|
||||||
DbType.DateTime, DbType.Double, DbType.Double, DbType.Int64,
|
SqlType.DateTime, SqlType.Double, SqlType.Double, SqlType.Int64,
|
||||||
DbType.Int32, DbType.SByte, DbType.Int16, DbType.Int32,
|
SqlType.Int32, SqlType.SByte, SqlType.Int16, SqlType.Int32,
|
||||||
DbType.Int64, DbType.Int64, DbType.SByte, DbType.Int16,
|
SqlType.Int64, SqlType.Int64, SqlType.SByte, SqlType.Int16,
|
||||||
DbType.Int32, DbType.Int64, DbType.Int64, DbType.Int32,
|
SqlType.Int32, SqlType.Int64, SqlType.Int64, SqlType.Int32,
|
||||||
DbType.Double, DbType.Single, DbType.Int16, DbType.UInt16,
|
SqlType.Double, SqlType.Single, SqlType.Int16, SqlType.UInt16,
|
||||||
DbType.String, DbType.String, DbType.DateTime, DbType.Byte,
|
SqlType.String, SqlType.String, SqlType.DateTime, SqlType.Byte,
|
||||||
DbType.SByte, DbType.UInt32, DbType.Byte, DbType.UInt16,
|
SqlType.SByte, SqlType.UInt32, SqlType.Byte, SqlType.UInt16,
|
||||||
DbType.UInt32, DbType.UInt64, DbType.UInt64, DbType.UInt64,
|
SqlType.UInt32, SqlType.UInt64, SqlType.UInt64, SqlType.UInt64,
|
||||||
DbType.Byte, DbType.UInt16, DbType.UInt32, DbType.UInt64,
|
SqlType.Byte, SqlType.UInt16, SqlType.UInt32, SqlType.UInt64,
|
||||||
DbType.String,
|
SqlType.String,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
enum TypeAffinity {
|
enum TypeAffinity
|
||||||
|
{
|
||||||
Uninitialized = 0,
|
Uninitialized = 0,
|
||||||
Int64 = 1,
|
Int64 = 1,
|
||||||
Double = 2,
|
Double = 2,
|
||||||
@ -567,12 +532,14 @@ namespace MCGalaxy.SQL {
|
|||||||
DateTime = 10,
|
DateTime = 10,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SQLiteType {
|
struct SQLiteType
|
||||||
public DbType Type;
|
{
|
||||||
|
public SqlType Type;
|
||||||
public TypeAffinity Affinity;
|
public TypeAffinity Affinity;
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class SQLiteDataReader : IDataReader {
|
public sealed class SQLiteDataReader : ISqlReader
|
||||||
|
{
|
||||||
SQLiteCommand _command;
|
SQLiteCommand _command;
|
||||||
SQLiteStatement stmt;
|
SQLiteStatement stmt;
|
||||||
int readState, rowsAffected, columns;
|
int readState, rowsAffected, columns;
|
||||||
@ -584,8 +551,8 @@ namespace MCGalaxy.SQL {
|
|||||||
NextResult();
|
NextResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose() { Close(); }
|
public override void Dispose() { Close(); }
|
||||||
public void Close() {
|
public override void Close() {
|
||||||
_command = null;
|
_command = null;
|
||||||
stmt = null;
|
stmt = null;
|
||||||
fieldNames = null;
|
fieldNames = null;
|
||||||
@ -595,81 +562,62 @@ namespace MCGalaxy.SQL {
|
|||||||
void CheckClosed() {
|
void CheckClosed() {
|
||||||
if (_command == null)
|
if (_command == null)
|
||||||
throw new InvalidOperationException("DataReader has been closed");
|
throw new InvalidOperationException("DataReader has been closed");
|
||||||
if (_command.Connection.State != ConnectionState.Open)
|
|
||||||
throw new InvalidOperationException("Connection was closed, statement was terminated");
|
SQLiteConnection.Check(_command.conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Depth { get { return 0; } }
|
public override int FieldCount { get { return columns; } }
|
||||||
public int FieldCount { get { return columns; } }
|
|
||||||
|
|
||||||
void VerifyForGet() {
|
void VerifyForGet() {
|
||||||
CheckClosed();
|
CheckClosed();
|
||||||
if (readState != 0) throw new InvalidOperationException("No current row");
|
if (readState != 0) throw new InvalidOperationException("No current row");
|
||||||
}
|
}
|
||||||
|
|
||||||
public long GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length) {
|
public override bool GetBoolean(int i) { return GetInt32(i) != 0; }
|
||||||
throw new NotSupportedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public IDataReader GetData(int i) { throw new NotSupportedException(); }
|
public override byte[] GetBytes(int i) {
|
||||||
public decimal GetDecimal(int i) { throw new NotSupportedException(); }
|
|
||||||
public Guid GetGuid(int i) { throw new NotSupportedException(); }
|
|
||||||
public DataTable GetSchemaTable() { throw new NotSupportedException(); }
|
|
||||||
|
|
||||||
public bool GetBoolean(int i) { return GetInt32(i) != 0; }
|
|
||||||
public byte GetByte(int i) { return (byte)GetInt32(i); }
|
|
||||||
public char GetChar(int i) { return (char)GetInt32(i); }
|
|
||||||
|
|
||||||
public long GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length) {
|
|
||||||
if (CheckAffinity(i) == TypeAffinity.Blob)
|
if (CheckAffinity(i) == TypeAffinity.Blob)
|
||||||
return stmt.GetBytes(i, (int)fieldOffset, buffer, bufferoffset, length);
|
return stmt.GetBytes(i);
|
||||||
throw new InvalidCastException();
|
throw new InvalidCastException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetDataTypeName(int i) {
|
public override DateTime GetDateTime(int i) {
|
||||||
VerifyForGet();
|
|
||||||
return stmt.ColumnType(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DateTime GetDateTime(int i) {
|
|
||||||
TypeAffinity aff = CheckAffinity(i);
|
TypeAffinity aff = CheckAffinity(i);
|
||||||
if (aff == TypeAffinity.Int64 || aff == TypeAffinity.Double || aff == TypeAffinity.Text)
|
if (aff == TypeAffinity.Int64 || aff == TypeAffinity.Double || aff == TypeAffinity.Text)
|
||||||
return stmt.GetDateTime(i);
|
return stmt.GetDateTime(i);
|
||||||
throw new NotSupportedException();
|
throw new NotSupportedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public double GetDouble(int i) {
|
public override double GetDouble(int i) {
|
||||||
TypeAffinity aff = CheckAffinity(i);
|
TypeAffinity aff = CheckAffinity(i);
|
||||||
if (aff == TypeAffinity.Int64 || aff == TypeAffinity.Double)
|
if (aff == TypeAffinity.Int64 || aff == TypeAffinity.Double)
|
||||||
return stmt.GetDouble(i);
|
return stmt.GetDouble(i);
|
||||||
throw new NotSupportedException();
|
throw new NotSupportedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Type GetFieldType(int i) {
|
public override Type GetFieldType(int i) {
|
||||||
SQLiteType t = GetSQLiteType(i);
|
SQLiteType t = GetSQLiteType(i);
|
||||||
if (t.Type == DbType.Object)
|
if (t.Type == SqlType.Object)
|
||||||
return SQLiteConvert.affinity_to_type[(int)t.Affinity];
|
return SQLiteConvert.affinity_to_type[(int)t.Affinity];
|
||||||
else
|
else
|
||||||
return SQLiteConvert.dbtype_to_type[(int)t.Type];
|
return SQLiteConvert.sqltype_to_type[(int)t.Type];
|
||||||
}
|
}
|
||||||
|
|
||||||
public float GetFloat(int i) { return (float)GetDouble(i); }
|
public override string GetName(int i) { return stmt.ColumnName(i); }
|
||||||
public short GetInt16(int i) { return (short)GetInt32(i); }
|
|
||||||
public string GetName(int i) { return stmt.ColumnName(i); }
|
|
||||||
|
|
||||||
public int GetInt32(int i) {
|
public override int GetInt32(int i) {
|
||||||
if (CheckAffinity(i) == TypeAffinity.Int64)
|
if (CheckAffinity(i) == TypeAffinity.Int64)
|
||||||
return stmt.GetInt32(i);
|
return stmt.GetInt32(i);
|
||||||
throw new InvalidCastException();
|
throw new InvalidCastException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public long GetInt64(int i) {
|
public override long GetInt64(int i) {
|
||||||
if (CheckAffinity(i) == TypeAffinity.Int64)
|
if (CheckAffinity(i) == TypeAffinity.Int64)
|
||||||
return stmt.GetInt64(i);
|
return stmt.GetInt64(i);
|
||||||
throw new InvalidCastException();
|
throw new InvalidCastException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetOrdinal(string name) {
|
public override int GetOrdinal(string name) {
|
||||||
VerifyForGet();
|
VerifyForGet();
|
||||||
if (fieldNames == null) fieldNames = new string[columns];
|
if (fieldNames == null) fieldNames = new string[columns];
|
||||||
|
|
||||||
@ -684,23 +632,15 @@ namespace MCGalaxy.SQL {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetString(int i) { return stmt.GetText(i); }
|
public override string GetString(int i) { return stmt.GetText(i); }
|
||||||
|
|
||||||
public object GetValue(int i) {
|
public override object GetValue(int i) {
|
||||||
VerifyForGet();
|
VerifyForGet();
|
||||||
SQLiteType t = GetSQLiteType(i);
|
SQLiteType t = GetSQLiteType(i);
|
||||||
return stmt.GetValue(i, t);
|
return stmt.GetValue(i, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetValues(object[] values) {
|
public override bool IsDBNull(int i) {
|
||||||
int count = Math.Min(columns, values.Length);
|
|
||||||
for (int i = 0; i < count; i++) { values[i] = GetValue(i); }
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsClosed { get { return _command == null; } }
|
|
||||||
|
|
||||||
public bool IsDBNull(int i) {
|
|
||||||
VerifyForGet();
|
VerifyForGet();
|
||||||
return stmt.ColumnAffinity(i) == TypeAffinity.Null;
|
return stmt.ColumnAffinity(i) == TypeAffinity.Null;
|
||||||
}
|
}
|
||||||
@ -753,7 +693,7 @@ namespace MCGalaxy.SQL {
|
|||||||
return typ;
|
return typ;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Read() {
|
public override bool Read() {
|
||||||
CheckClosed();
|
CheckClosed();
|
||||||
|
|
||||||
// First Row was already read at NextResult() level, so don't step again here
|
// First Row was already read at NextResult() level, so don't step again here
|
||||||
@ -766,12 +706,11 @@ namespace MCGalaxy.SQL {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int RecordsAffected { get { return rowsAffected; } }
|
public override int RowsAffected { get { return rowsAffected; } }
|
||||||
public object this[string name] { get { return GetValue(GetOrdinal(name)); } }
|
|
||||||
public object this[int i] { get { return GetValue(i); } }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class SQLiteException : ExternalException {
|
sealed class SQLiteException : ExternalException
|
||||||
|
{
|
||||||
SQLiteErrorCode _code;
|
SQLiteErrorCode _code;
|
||||||
|
|
||||||
public SQLiteException(SQLiteErrorCode code, string message)
|
public SQLiteException(SQLiteErrorCode code, string message)
|
||||||
@ -833,7 +772,8 @@ namespace MCGalaxy.SQL {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static class SQLiteErrorCodes {
|
static class SQLiteErrorCodes
|
||||||
|
{
|
||||||
public const int Unknown = -1;
|
public const int Unknown = -1;
|
||||||
public const int Ok = 0;
|
public const int Ok = 0;
|
||||||
public const int Error = 1;
|
public const int Error = 1;
|
||||||
@ -843,79 +783,8 @@ namespace MCGalaxy.SQL {
|
|||||||
public const int Done = 101;
|
public const int Done = 101;
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class SQLiteParameter : IDbDataParameter {
|
sealed class SQLiteStatement : IDisposable
|
||||||
int type = -1;
|
{
|
||||||
object value;
|
|
||||||
string name;
|
|
||||||
|
|
||||||
public DbType DbType {
|
|
||||||
get {
|
|
||||||
if (type == -1) {
|
|
||||||
if (value != null && value != DBNull.Value) {
|
|
||||||
return SQLiteConvert.TypeToDbType(value.GetType());
|
|
||||||
}
|
|
||||||
return DbType.String; // Unassigned default value is String
|
|
||||||
}
|
|
||||||
return (DbType)type;
|
|
||||||
}
|
|
||||||
set { type = (int)value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public string ParameterName { get { return name; } set { name = value; } }
|
|
||||||
|
|
||||||
public object Value {
|
|
||||||
get { return value; }
|
|
||||||
set {
|
|
||||||
this.value = value;
|
|
||||||
// If the DbType has never been assigned, try to glean one from the value's datatype
|
|
||||||
if (type == -1 && value != null && value != DBNull.Value)
|
|
||||||
type = (int)SQLiteConvert.TypeToDbType(value.GetType());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsNullable { get { return true; } set { } }
|
|
||||||
public string SourceColumn { get { return ""; } set { } }
|
|
||||||
public ParameterDirection Direction { get { return 0; } set { } }
|
|
||||||
public DataRowVersion SourceVersion { get { return 0; } set { } }
|
|
||||||
|
|
||||||
public byte Precision { get { return 0; } set { } }
|
|
||||||
public byte Scale { get { return 0; } set { } }
|
|
||||||
public int Size { get { return 0; } set { } }
|
|
||||||
}
|
|
||||||
|
|
||||||
public sealed class SQLiteParameterCollection : IDataParameterCollection {
|
|
||||||
internal List<SQLiteParameter> list = new List<SQLiteParameter>();
|
|
||||||
public bool IsSynchronized { get { return false; } }
|
|
||||||
public bool IsFixedSize { get { return false; } }
|
|
||||||
public bool IsReadOnly { get { return false; } }
|
|
||||||
public object SyncRoot { get { return null; } }
|
|
||||||
public IEnumerator GetEnumerator() { return null; }
|
|
||||||
|
|
||||||
public int Add(object value) {
|
|
||||||
list.Add((SQLiteParameter)value);
|
|
||||||
return list.Count - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Clear() { list.Clear(); }
|
|
||||||
public int Count { get { return list.Count; } }
|
|
||||||
|
|
||||||
public bool Contains(string name) { return false; }
|
|
||||||
public bool Contains(object value) { return false; }
|
|
||||||
public void CopyTo(Array array, int index) { }
|
|
||||||
|
|
||||||
public object this[string name] { get {return null; } set { } }
|
|
||||||
public object this[int index] { get {return null; } set { } }
|
|
||||||
|
|
||||||
public int IndexOf(string name) { return -1; }
|
|
||||||
public int IndexOf(object value) { return -1; }
|
|
||||||
public void Insert(int index, object value) { }
|
|
||||||
|
|
||||||
public void Remove(object value) { }
|
|
||||||
public void RemoveAt(string name) { }
|
|
||||||
public void RemoveAt(int index) { }
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed class SQLiteStatement : IDisposable {
|
|
||||||
IntPtr handle;
|
IntPtr handle;
|
||||||
internal SQLiteConnection conn;
|
internal SQLiteConnection conn;
|
||||||
string[] paramNames;
|
string[] paramNames;
|
||||||
@ -980,14 +849,15 @@ namespace MCGalaxy.SQL {
|
|||||||
return SQLiteConvert.FromUTF8(p, -1);
|
return SQLiteConvert.FromUTF8(p, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void BindAll(SQLiteParameterCollection args) {
|
internal void BindAll(List<string> names, List<object> values) {
|
||||||
if (paramNames == null || args.list.Count == 0) return;
|
if (paramNames == null || names.Count == 0) return;
|
||||||
|
|
||||||
foreach (SQLiteParameter arg in args.list) {
|
for (int idx = 0; idx < names.Count; idx++)
|
||||||
int i = FindParameter(arg.ParameterName);
|
{
|
||||||
|
int i = FindParameter(names[idx]);
|
||||||
if (i == -1) continue;
|
if (i == -1) continue;
|
||||||
|
|
||||||
SQLiteErrorCode n = BindParameter(i + 1, arg);
|
SQLiteErrorCode n = BindParameter(i + 1, values[idx]);
|
||||||
if (n != SQLiteErrorCodes.Ok) throw new SQLiteException(n, conn.GetLastError());
|
if (n != SQLiteErrorCodes.Ok) throw new SQLiteException(n, conn.GetLastError());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1000,48 +870,38 @@ namespace MCGalaxy.SQL {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
SQLiteErrorCode BindParameter(int i, SQLiteParameter param) {
|
SQLiteErrorCode BindParameter(int i, object obj) {
|
||||||
object obj = param.Value;
|
|
||||||
DbType type = param.DbType;
|
|
||||||
if (obj != null && type == DbType.Object)
|
|
||||||
type = SQLiteConvert.TypeToDbType(obj.GetType());
|
|
||||||
|
|
||||||
if (obj == null || obj == DBNull.Value) {
|
if (obj == null || obj == DBNull.Value) {
|
||||||
return Interop.sqlite3_bind_null(handle, i);
|
return Interop.sqlite3_bind_null(handle, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SqlType type = SQLiteConvert.TypeToDbType(obj.GetType());
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case DbType.DateTime:
|
case SqlType.DateTime:
|
||||||
//
|
return Bind_DateTime(i, Convert.ToDateTime(obj, CultureInfo.InvariantCulture));
|
||||||
// NOTE: The old method (commented below) does not honor the selected date format
|
case SqlType.Boolean:
|
||||||
// for the connection.
|
|
||||||
// _sql.Bind_DateTime(this, index, Convert.ToDateTime(obj, cultureInfo));
|
|
||||||
return Bind_DateTime(i, (obj is string) ?
|
|
||||||
SQLiteConvert.ToDateTime((string)obj) :
|
|
||||||
Convert.ToDateTime(obj, CultureInfo.InvariantCulture));
|
|
||||||
case DbType.Boolean:
|
|
||||||
return Bind_Int32(i, Convert.ToBoolean(obj) ? 1 : 0);
|
return Bind_Int32(i, Convert.ToBoolean(obj) ? 1 : 0);
|
||||||
case DbType.SByte:
|
case SqlType.SByte:
|
||||||
return Bind_Int32(i, Convert.ToSByte(obj));
|
return Bind_Int32(i, Convert.ToSByte(obj));
|
||||||
case DbType.Int16:
|
case SqlType.Int16:
|
||||||
return Bind_Int32(i, Convert.ToInt16(obj));
|
return Bind_Int32(i, Convert.ToInt16(obj));
|
||||||
case DbType.Int32:
|
case SqlType.Int32:
|
||||||
return Bind_Int32(i, Convert.ToInt32(obj));
|
return Bind_Int32(i, Convert.ToInt32(obj));
|
||||||
case DbType.Int64:
|
case SqlType.Int64:
|
||||||
return Bind_Int64(i, Convert.ToInt64(obj));
|
return Bind_Int64(i, Convert.ToInt64(obj));
|
||||||
case DbType.Byte:
|
case SqlType.Byte:
|
||||||
return Bind_Int32(i, Convert.ToByte(obj));
|
return Bind_Int32(i, Convert.ToByte(obj));
|
||||||
case DbType.UInt16:
|
case SqlType.UInt16:
|
||||||
return Bind_Int32(i, Convert.ToUInt16(obj));
|
return Bind_Int32(i, Convert.ToUInt16(obj));
|
||||||
case DbType.UInt32:
|
case SqlType.UInt32:
|
||||||
return Bind_Int32(i, (int)Convert.ToUInt32(obj));
|
return Bind_Int32(i, (int)Convert.ToUInt32(obj));
|
||||||
case DbType.UInt64:
|
case SqlType.UInt64:
|
||||||
return Bind_Int64(i, (long)Convert.ToUInt64(obj));
|
return Bind_Int64(i, (long)Convert.ToUInt64(obj));
|
||||||
case DbType.Single:
|
case SqlType.Single:
|
||||||
case DbType.Double:
|
case SqlType.Double:
|
||||||
case DbType.Decimal:
|
case SqlType.Decimal:
|
||||||
return Interop.sqlite3_bind_double(handle, i, Convert.ToDouble(obj));
|
return Interop.sqlite3_bind_double(handle, i, Convert.ToDouble(obj));
|
||||||
case DbType.Binary:
|
case SqlType.Binary:
|
||||||
byte[] b = (byte[])obj;
|
byte[] b = (byte[])obj;
|
||||||
return Interop.sqlite3_bind_blob(handle, i, b, b.Length, (IntPtr)(-1));
|
return Interop.sqlite3_bind_blob(handle, i, b, b.Length, (IntPtr)(-1));
|
||||||
default:
|
default:
|
||||||
@ -1067,14 +927,11 @@ namespace MCGalaxy.SQL {
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal object GetValue(int index, SQLiteType typ) {
|
internal object GetValue(int index, SQLiteType typ) {
|
||||||
if (typ.Type == DbType.DateTime) return GetDateTime(index);
|
if (typ.Type == SqlType.DateTime) return GetDateTime(index);
|
||||||
|
|
||||||
switch (typ.Affinity) {
|
switch (typ.Affinity) {
|
||||||
case TypeAffinity.Blob:
|
case TypeAffinity.Blob:
|
||||||
int n = Interop.sqlite3_column_bytes(handle, index);
|
return GetBytes(index);
|
||||||
byte[] b = new byte[n];
|
|
||||||
GetBytes(index, 0, b, 0, n);
|
|
||||||
return b;
|
|
||||||
case TypeAffinity.Double:
|
case TypeAffinity.Double:
|
||||||
return GetDouble(index);
|
return GetDouble(index);
|
||||||
case TypeAffinity.Int64:
|
case TypeAffinity.Int64:
|
||||||
@ -1106,30 +963,26 @@ namespace MCGalaxy.SQL {
|
|||||||
return SQLiteConvert.ToDateTime(GetText(index));
|
return SQLiteConvert.ToDateTime(GetText(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
internal long GetBytes(int index, int srcOffset, byte[] dst, int dstOffset, int dstLen) {
|
internal byte[] GetBytes(int index) {
|
||||||
int srcLen = Interop.sqlite3_column_bytes(handle, index);
|
int srcLen = Interop.sqlite3_column_bytes(handle, index);
|
||||||
if (dst == null) return srcLen;
|
if (srcLen <= 0) return null;
|
||||||
|
byte[] dst = new byte[srcLen];
|
||||||
|
|
||||||
int count = dstLen;
|
|
||||||
if (count + dstOffset > dst.Length) count = dst.Length - dstOffset;
|
|
||||||
if (count + srcOffset > srcLen) count = srcLen - srcOffset;
|
|
||||||
|
|
||||||
if (count <= 0) return 0;
|
|
||||||
IntPtr src = Interop.sqlite3_column_blob(handle, index);
|
IntPtr src = Interop.sqlite3_column_blob(handle, index);
|
||||||
Marshal.Copy((IntPtr)(src.ToInt64() + srcOffset), dst, dstOffset, count);
|
Marshal.Copy(src, dst, 0, srcLen);
|
||||||
return count;
|
return dst;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class SQLiteTransaction : IDbTransaction {
|
public sealed class SQLiteTransaction : ISqlTransaction
|
||||||
|
{
|
||||||
SQLiteConnection conn;
|
SQLiteConnection conn;
|
||||||
|
|
||||||
internal SQLiteTransaction(SQLiteConnection connection) {
|
internal SQLiteTransaction(SQLiteConnection connection) {
|
||||||
conn = connection;
|
conn = connection;
|
||||||
if (conn._transactionLevel++ == 0) {
|
if (conn._transactionLevel++ == 0) {
|
||||||
try {
|
try {
|
||||||
using (IDbCommand cmd = conn.CreateCommand()) {
|
using (ISqlCommand cmd = conn.CreateCommand("BEGIN IMMEDIATE")) {
|
||||||
cmd.CommandText = "BEGIN IMMEDIATE";
|
|
||||||
cmd.ExecuteNonQuery();
|
cmd.ExecuteNonQuery();
|
||||||
}
|
}
|
||||||
} catch (SQLiteException) {
|
} catch (SQLiteException) {
|
||||||
@ -1141,29 +994,25 @@ namespace MCGalaxy.SQL {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool disposed;
|
bool disposed;
|
||||||
public void Dispose() {
|
public override void Dispose() {
|
||||||
if (disposed) return;
|
if (disposed) return;
|
||||||
if (IsValid(false)) IssueRollback(false);
|
if (IsValid(false)) IssueRollback(false);
|
||||||
disposed = true;
|
disposed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Commit() {
|
public override void Commit() {
|
||||||
SQLiteConnection.Check(conn);
|
SQLiteConnection.Check(conn);
|
||||||
IsValid(true);
|
IsValid(true);
|
||||||
|
|
||||||
if (--conn._transactionLevel == 0) {
|
if (--conn._transactionLevel == 0) {
|
||||||
using (IDbCommand cmd = conn.CreateCommand()) {
|
using (ISqlCommand cmd = conn.CreateCommand("COMMIT")) {
|
||||||
cmd.CommandText = "COMMIT";
|
|
||||||
cmd.ExecuteNonQuery();
|
cmd.ExecuteNonQuery();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
conn = null;
|
conn = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IDbConnection Connection { get { return conn; } }
|
public override void Rollback() {
|
||||||
public IsolationLevel IsolationLevel { get { return IsolationLevel.Serializable; } }
|
|
||||||
|
|
||||||
public void Rollback() {
|
|
||||||
SQLiteConnection.Check(conn);
|
SQLiteConnection.Check(conn);
|
||||||
IsValid(true);
|
IsValid(true);
|
||||||
IssueRollback(true);
|
IssueRollback(true);
|
||||||
@ -1173,8 +1022,7 @@ namespace MCGalaxy.SQL {
|
|||||||
if (conn == null) return;
|
if (conn == null) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
using (IDbCommand cmd = conn.CreateCommand()) {
|
using (ISqlCommand cmd = conn.CreateCommand("ROLLBACK")) {
|
||||||
cmd.CommandText = "ROLLBACK";
|
|
||||||
cmd.ExecuteNonQuery();
|
cmd.ExecuteNonQuery();
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
@ -1189,7 +1037,7 @@ namespace MCGalaxy.SQL {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (conn.State != ConnectionState.Open) {
|
if (conn.handle == IntPtr.Zero) {
|
||||||
if (throwError) throw new SQLiteException("Connection was closed");
|
if (throwError) throw new SQLiteException("Connection was closed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user