diff --git a/README.md b/README.md index 6fad76d..a7a32e2 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,8 @@ If this folder does not exist create it in the root folder of your Unity project void ExecuteNonQuery(string query) //for SQL query like UPDATE, DELETE.... Dictionary ExecuteQuery(string query) //for SQL query like SELECT .... +###parameter escaping: +Just pass a List<> as the second parameter of this methods and include them in your query, with "?" or "@param" as in regular SQLite. ##for Android compatibility:
@@ -46,6 +48,7 @@ follow this simple steps and you can get full compatibility with android. * BLOB support by Jonathan Derrough @ http://jderrough.blogspot.com/ * modify by Santiago Bustamante @ busta117@gmail.com * Android compatibility by Thomas Olsen @ olsen.thomas@gmail.com + * Parameter escaping and iOS 64 bit compatibility by Scalia @ http://scalia.es
@@ -53,4 +56,4 @@ follow this simple steps and you can get full compatibility with android. * twitter: [@busta117](http://www.twitter.com/busta117) * mail: -* \ No newline at end of file +* diff --git a/SqliteDatabase.cs b/SqliteDatabase.cs index e3544c0..53e4593 100755 --- a/SqliteDatabase.cs +++ b/SqliteDatabase.cs @@ -1,6 +1,7 @@ using System; using System.Runtime.InteropServices; using System.Collections; +using System.Collections.Generic; using UnityEngine; /* @@ -12,12 +13,12 @@ * Android compatibility by Thomas Olsen @ olsen.thomas@gmail.com * * */ - + public class SqliteException : Exception { public SqliteException (string message) : base(message) { - + } } @@ -32,58 +33,76 @@ public class SqliteDatabase const int SQLITE_TEXT = 3; const int SQLITE_BLOB = 4; const int SQLITE_NULL = 5; - - [DllImport("sqlite3", EntryPoint = "sqlite3_open")] + + const int SQLITE_STATIC = 0; + const int SQLITE_TRANSIENT = -1; + + [DllImport("__Internal", EntryPoint = "sqlite3_open")] private static extern int sqlite3_open (string filename, out IntPtr db); - - [DllImport("sqlite3", EntryPoint = "sqlite3_close")] + + [DllImport("__Internal", EntryPoint = "sqlite3_close")] private static extern int sqlite3_close (IntPtr db); - - [DllImport("sqlite3", EntryPoint = "sqlite3_prepare_v2")] + + [DllImport("__Internal", EntryPoint = "sqlite3_prepare_v2")] private static extern int sqlite3_prepare_v2 (IntPtr db, string zSql, int nByte, out IntPtr ppStmpt, IntPtr pzTail); - - [DllImport("sqlite3", EntryPoint = "sqlite3_step")] + + [DllImport("__Internal", EntryPoint = "sqlite3_step")] private static extern int sqlite3_step (IntPtr stmHandle); - - [DllImport("sqlite3", EntryPoint = "sqlite3_finalize")] + + [DllImport("__Internal", EntryPoint = "sqlite3_finalize")] private static extern int sqlite3_finalize (IntPtr stmHandle); - - [DllImport("sqlite3", EntryPoint = "sqlite3_errmsg")] + + [DllImport("__Internal", EntryPoint = "sqlite3_errmsg")] private static extern IntPtr sqlite3_errmsg (IntPtr db); - - [DllImport("sqlite3", EntryPoint = "sqlite3_column_count")] + + [DllImport("__Internal", EntryPoint = "sqlite3_column_count")] private static extern int sqlite3_column_count (IntPtr stmHandle); - - [DllImport("sqlite3", EntryPoint = "sqlite3_column_name")] + + [DllImport("__Internal", EntryPoint = "sqlite3_column_name")] private static extern IntPtr sqlite3_column_name (IntPtr stmHandle, int iCol); - - [DllImport("sqlite3", EntryPoint = "sqlite3_column_type")] + + [DllImport("__Internal", EntryPoint = "sqlite3_column_type")] private static extern int sqlite3_column_type (IntPtr stmHandle, int iCol); - - [DllImport("sqlite3", EntryPoint = "sqlite3_column_int")] + + [DllImport("__Internal", EntryPoint = "sqlite3_column_int")] private static extern int sqlite3_column_int (IntPtr stmHandle, int iCol); - - [DllImport("sqlite3", EntryPoint = "sqlite3_column_text")] + + [DllImport("__Internal", EntryPoint = "sqlite3_column_text")] private static extern IntPtr sqlite3_column_text (IntPtr stmHandle, int iCol); - - [DllImport("sqlite3", EntryPoint = "sqlite3_column_double")] + + [DllImport("__Internal", EntryPoint = "sqlite3_column_double")] private static extern double sqlite3_column_double (IntPtr stmHandle, int iCol); - - [DllImport("sqlite3", EntryPoint = "sqlite3_column_blob")] + + [DllImport("__Internal", EntryPoint = "sqlite3_column_blob")] private static extern IntPtr sqlite3_column_blob (IntPtr stmHandle, int iCol); - - [DllImport("sqlite3", EntryPoint = "sqlite3_column_bytes")] + + [DllImport("__Internal", EntryPoint = "sqlite3_column_bytes")] private static extern int sqlite3_column_bytes (IntPtr stmHandle, int iCol); + [DllImport("__Internal", EntryPoint = "sqlite3_bind_text")] + private static extern int sqlite3_bind_text(IntPtr stmHandle, int iCol, string value, int nByte, int mode); + + [DllImport("__Internal", EntryPoint = "sqlite3_bind_int")] + private static extern int sqlite3_bind_int(IntPtr stmHandle, int iCol, int value); + + [DllImport("__Internal", EntryPoint = "sqlite3_bind_int64")] + private static extern int sqlite3_bind_int64(IntPtr stmHandle, int iCol, long value); + + [DllImport("__Internal", EntryPoint = "sqlite3_bind_double")] + private static extern int sqlite3_bind_double(IntPtr stmHandle, int iCol, double value); + + [DllImport("__Internal", EntryPoint = "sqlite3_bind_null")] + private static extern int sqlite3_bind_null(IntPtr stmHandle, int iCol); + private IntPtr _connection; - + private bool IsConnectionOpen { get; set; } private string pathDB; - #region Public Methods - + #region Public Methods + /// /// Initializes a new instance of the class. /// @@ -115,13 +134,13 @@ public SqliteDatabase (string dbName) } else { // Mac, Windows, Iphone - + //validate the existens of the DB in the original folder (folder "streamingAssets") if (System.IO.File.Exists (sourcePath)) { - + //copy file - alle systems except Android System.IO.File.Copy (sourcePath, pathDB, true); - + } else { CanExQuery = false; Debug.Log ("ERROR: the file DB named " + dbName + " doesn't exist in the StreamingAssets Folder, please copy it there."); @@ -142,50 +161,57 @@ private void Open (string path) if (IsConnectionOpen) { throw new SqliteException ("There is already an open connection"); } - + if (sqlite3_open (path, out _connection) != SQLITE_OK) { throw new SqliteException ("Could not open database file: " + path); } - + IsConnectionOpen = true; } - + private void Close () { if (IsConnectionOpen) { sqlite3_close (_connection); } - + IsConnectionOpen = false; } - + /// /// Executes a Update, Delete, etc query. /// /// /// Query. /// + /// + /// Parameters. + /// /// /// Is thrown when the sqlite exception. /// - public void ExecuteNonQuery (string query) + public void ExecuteNonQuery (string query, List parameters = null) { if (!CanExQuery) { Debug.Log ("ERROR: Can't execute the query, verify DB origin file"); return; } - + this.Open (); if (!IsConnectionOpen) { throw new SqliteException ("SQLite database is not open."); } - + IntPtr stmHandle = Prepare (query); - + + if (null != parameters) { + BindParameters(stmHandle, parameters); + } + if (sqlite3_step (stmHandle) != SQLITE_DONE) { throw new SqliteException ("Could not execute SQL statement."); } - + Finalize (stmHandle); this.Close (); } @@ -199,10 +225,13 @@ public void ExecuteNonQuery (string query) /// /// Query. /// + /// + /// Parameters. + /// /// /// Is thrown when the sqlite exception. /// - public DataTable ExecuteQuery (string query) + public DataTable ExecuteQuery (string query, List parameters = null) { if (!CanExQuery) { Debug.Log ("ERROR: Can't execute the query, verify DB origin file"); @@ -213,17 +242,20 @@ public DataTable ExecuteQuery (string query) if (!IsConnectionOpen) { throw new SqliteException ("SQLite database is not open."); } - + IntPtr stmHandle = Prepare (query); - + + if (null != parameters) { + BindParameters(stmHandle, parameters); + } + int columnCount = sqlite3_column_count (stmHandle); - + var dataTable = new DataTable (); for (int i = 0; i < columnCount; i++) { string columnName = Marshal.PtrToStringAnsi (sqlite3_column_name (stmHandle, i)); dataTable.Columns.Add (columnName); } - //populate datatable while (sqlite3_step(stmHandle) == SQLITE_ROW) { @@ -233,16 +265,16 @@ public DataTable ExecuteQuery (string query) case SQLITE_INTEGER: row [i] = sqlite3_column_int (stmHandle, i); break; - + case SQLITE_TEXT: IntPtr text = sqlite3_column_text (stmHandle, i); row [i] = Marshal.PtrToStringAnsi (text); break; - + case SQLITE_FLOAT: row [i] = sqlite3_column_double (stmHandle, i); break; - + case SQLITE_BLOB: IntPtr blob = sqlite3_column_blob (stmHandle, i); int size = sqlite3_column_bytes (stmHandle, i); @@ -256,48 +288,79 @@ public DataTable ExecuteQuery (string query) break; } } - + dataTable.AddRow (row); } - + Finalize (stmHandle); this.Close (); return dataTable; } - + public void ExecuteScript (string script) { string[] statements = script.Split (';'); - + foreach (string statement in statements) { if (!string.IsNullOrEmpty (statement.Trim ())) { ExecuteNonQuery (statement); } } } - - #endregion - - #region Private Methods - + + #endregion + + #region Private Methods + private IntPtr Prepare (string query) { IntPtr stmHandle; - + if (sqlite3_prepare_v2 (_connection, query, query.Length, out stmHandle, IntPtr.Zero) != SQLITE_OK) { IntPtr errorMsg = sqlite3_errmsg (_connection); throw new SqliteException (Marshal.PtrToStringAnsi (errorMsg)); } - + return stmHandle; } - + + private void BindParameters(IntPtr stmHandle, List parameters) + { + for(int i=0; i