mirror of
https://github.com/ClassiCube/MCGalaxy.git
synced 2025-09-25 22:30:52 -04:00
More work on native sqlite backend.
This commit is contained in:
parent
bff8687f2a
commit
06887a5891
@ -53,7 +53,7 @@ namespace MCGalaxy.SQL.Native {
|
|||||||
BindParam(args[i]);
|
BindParam(args[i]);
|
||||||
|
|
||||||
int code = Interop.sqlite3_step(Statement);
|
int code = Interop.sqlite3_step(Statement);
|
||||||
if (code > 0 && code != 101) throw new NativeException(code);
|
if (code > 0 && code != Interop.Done) throw new NativeException(code);
|
||||||
code = Interop.sqlite3_reset(Statement);
|
code = Interop.sqlite3_reset(Statement);
|
||||||
if (code > 0) throw new NativeException(code);
|
if (code > 0) throw new NativeException(code);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -24,29 +24,62 @@ namespace MCGalaxy.SQL.Native {
|
|||||||
|
|
||||||
unsafe sealed class NativeReader {
|
unsafe sealed class NativeReader {
|
||||||
|
|
||||||
int cols;
|
int cols;
|
||||||
int[] codes;
|
|
||||||
public void ReadColumns(NativeCommand cmd, DataTable results) {
|
public void ReadColumns(NativeCommand cmd, DataTable results) {
|
||||||
|
results.Columns.Clear();
|
||||||
cols = Interop.sqlite3_column_count(cmd.Statement);
|
cols = Interop.sqlite3_column_count(cmd.Statement);
|
||||||
codes = new int[cols];
|
|
||||||
|
|
||||||
for (int i = 0; i < cols; i++) {
|
for (int i = 0; i < cols; i++) {
|
||||||
IntPtr namePtr = Interop.sqlite3_column_name(cmd.Statement, i);
|
IntPtr namePtr = Interop.sqlite3_column_name(cmd.Statement, i);
|
||||||
string name = new String((sbyte*)namePtr);
|
string name = new String((sbyte*)namePtr);
|
||||||
int code = Interop.sqlite3_column_type(cmd.Statement, i);
|
results.Columns.Add(new DataColumn(name));
|
||||||
codes[i] = code;
|
|
||||||
|
|
||||||
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) {
|
public void ReadRows(NativeCommand cmd, DataTable results) {
|
||||||
|
while (true) {
|
||||||
|
int code = Interop.sqlite3_step(cmd.Statement);
|
||||||
|
if (code == Interop.RowReady) {
|
||||||
|
object[] values = new object[cols];
|
||||||
|
for (int i = 0; i < values.Length; i++)
|
||||||
|
values[i] = ParseValue(cmd.Statement, i);
|
||||||
|
|
||||||
|
results.Rows.Add(values); continue;
|
||||||
|
}
|
||||||
|
if (code == Interop.Done) return;
|
||||||
|
if (code > 0) throw new NativeException(code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe object ParseValue(IntPtr stmt, int i) {
|
||||||
|
int code = Interop.sqlite3_column_type(stmt, i);
|
||||||
|
switch (code) {
|
||||||
|
case 1: return Interop.sqlite3_column_int64(stmt, i);
|
||||||
|
case 2: return Interop.sqlite3_column_double(stmt, i);
|
||||||
|
case 3: return MakeString(stmt, i);
|
||||||
|
case 4: return MakeBlob(stmt, i);
|
||||||
|
case 5: return null;
|
||||||
|
}
|
||||||
|
throw new InvalidOperationException("Invalid type code: " + code);
|
||||||
|
}
|
||||||
|
|
||||||
|
string MakeString(IntPtr stmt, int i) {
|
||||||
|
int count = Interop.sqlite3_column_bytes(stmt, i);
|
||||||
|
if (count == 0) return "";
|
||||||
|
|
||||||
|
byte* ptr = (byte*)Interop.sqlite3_column_text(stmt, i);
|
||||||
|
return Encoding.UTF8.GetString(ptr, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] MakeBlob(IntPtr stmt, int i) {
|
||||||
|
int count = Interop.sqlite3_column_bytes(stmt, i);
|
||||||
|
if (count == 0) return new byte[0];
|
||||||
|
|
||||||
|
byte* ptr = (byte*)Interop.sqlite3_column_blob(stmt, i);
|
||||||
|
byte[] dst = new byte[count];
|
||||||
|
for (int j = 0; j < count; j++)
|
||||||
|
dst[j] = ptr[j];
|
||||||
|
return dst;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -88,6 +88,9 @@ namespace MCGalaxy.SQL.Native {
|
|||||||
static Encoding encoding = Encoding.UTF8;
|
static Encoding encoding = Encoding.UTF8;
|
||||||
const CallingConvention conv = CallingConvention.Cdecl;
|
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) {
|
public static byte[] MakeUTF8(string input) {
|
||||||
int count = encoding.GetByteCount(input) + 1; // null terminator
|
int count = encoding.GetByteCount(input) + 1; // null terminator
|
||||||
byte[] chars = new byte[count];
|
byte[] chars = new byte[count];
|
||||||
@ -145,8 +148,11 @@ namespace MCGalaxy.SQL.Native {
|
|||||||
|
|
||||||
[DllImport("sqlite3.dll", CallingConvention = conv), SuppressUnmanagedCodeSecurity]
|
[DllImport("sqlite3.dll", CallingConvention = conv), SuppressUnmanagedCodeSecurity]
|
||||||
public static extern IntPtr sqlite3_column_text(IntPtr stmt, int iCol);
|
public static extern IntPtr sqlite3_column_text(IntPtr stmt, int iCol);
|
||||||
|
|
||||||
[DllImport("sqlite3.dll", CallingConvention = conv), SuppressUnmanagedCodeSecurity]
|
[DllImport("sqlite3.dll", CallingConvention = conv), SuppressUnmanagedCodeSecurity]
|
||||||
public static extern IntPtr sqlite3_column_text16(IntPtr stmt, int iCol);
|
public static extern IntPtr sqlite3_column_blob(IntPtr stmt, int iCol);
|
||||||
|
|
||||||
|
[DllImport("sqlite3.dll", CallingConvention = conv), SuppressUnmanagedCodeSecurity]
|
||||||
|
public static extern int sqlite3_column_bytes(IntPtr stmt, int iCol);
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user