internal override SqliteStatement Prepare(SqliteConnection cnn, string strSql, SqliteStatement previous, uint timeout, out string strRemain) { SqliteStatementHandle stmt = null; string ptr = null; int len = 0; int n = 17; int retries = 0; SqliteStatement cmd = null; var rnd = new Random(); var starttick = (uint)Environment.TickCount; while ((n == 17 || n == 6 || n == 5) && retries < 3) { n = UnsafeNativeMethods.sqlite3_prepare16(_sql, strSql, strSql.Length, out stmt, out ptr); len = -1; if (n == 17) { retries++; } else if (n == 1) { if (String.Compare(SQLiteLastError(), "near \"TYPES\": syntax error", StringComparison.OrdinalIgnoreCase) == 0) { int pos = strSql.IndexOf(';'); if (pos == -1) { pos = strSql.Length - 1; } string typedefs = strSql.Substring(0, pos + 1); strSql = strSql.Substring(pos + 1); strRemain = ""; while (cmd == null && strSql.Length > 0) { cmd = Prepare(cnn, strSql, previous, timeout, out strRemain); strSql = strRemain; } if (cmd != null) { cmd.SetTypes(typedefs); } return(cmd); } else if (_buildingSchema == false && String.Compare(SQLiteLastError(), 0, "no such table: TEMP.SCHEMA", 0, 26, StringComparison.OrdinalIgnoreCase) == 0) { strRemain = ""; _buildingSchema = true; try { while (cmd == null && strSql.Length > 0) { cmd = Prepare(cnn, strSql, previous, timeout, out strRemain); strSql = strRemain; } return(cmd); } finally { _buildingSchema = false; } } } else if (n == 6 || n == 5) // Locked -- delay a small amount before retrying { // Keep trying, but if we've exceeded the command's timeout, give up and throw an error if ((uint)Environment.TickCount - starttick > timeout) { throw new SqliteException(n, SQLiteLastError()); } else { // Otherwise sleep for a random amount of time up to 150ms Sleep(rnd.Next(1, 150)); } } } if (n > 0) { throw new SqliteException(n, SQLiteLastError()); } strRemain = UTF8ToString(ptr, len); var hdl = stmt; if (stmt != null) { cmd = new SqliteStatement(this, hdl, strSql.Substring(0, strSql.Length - strRemain.Length), previous); } return(cmd); }
internal override SqliteStatement Prepare(SqliteConnection cnn, string strSql, SqliteStatement previous, uint timeoutMS, out string strRemain) { IntPtr stmt = IntPtr.Zero; IntPtr ptr = IntPtr.Zero; int len = 0; int n = 17; int retries = 0; byte[] b = ToUTF8(strSql); string typedefs = null; SqliteStatement cmd = null; Random rnd = null; uint starttick = (uint)Environment.TickCount; GCHandle handle = GCHandle.Alloc(b, GCHandleType.Pinned); IntPtr psql = handle.AddrOfPinnedObject(); try { while ((n == 17 || n == 6 || n == 5) && retries < 3) { #if !SQLITE_STANDARD n = UnsafeNativeMethods.sqlite3_prepare_interop(_sql, psql, b.Length - 1, out stmt, out ptr, out len); #else n = UnsafeNativeMethods.sqlite3_prepare(_sql, psql, b.Length - 1, out stmt, out ptr); len = -1; #endif if (n == 17) { retries++; } else if (n == 1) { if (String.Compare(SQLiteLastError(), "near \"TYPES\": syntax error", StringComparison.OrdinalIgnoreCase) == 0) { int pos = strSql.IndexOf(';'); if (pos == -1) { pos = strSql.Length - 1; } typedefs = strSql.Substring(0, pos + 1); strSql = strSql.Substring(pos + 1); strRemain = ""; while (cmd == null && strSql.Length > 0) { cmd = Prepare(cnn, strSql, previous, timeoutMS, out strRemain); strSql = strRemain; } if (cmd != null) { cmd.SetTypes(typedefs); } return(cmd); } #if PLATFORM_COMPACTFRAMEWORK else if (_buildingSchema == false && String.Compare(SQLiteLastError(), 0, "no such table: TEMP.SCHEMA", 0, 26, StringComparison.OrdinalIgnoreCase) == 0) { strRemain = ""; _buildingSchema = true; try { ISQLiteSchemaExtensions ext = ((IServiceProvider)SqliteFactory.Instance).GetService(typeof(ISQLiteSchemaExtensions)) as ISQLiteSchemaExtensions; if (ext != null) { ext.BuildTempSchema(cnn); } while (cmd == null && strSql.Length > 0) { cmd = Prepare(cnn, strSql, previous, timeoutMS, out strRemain); strSql = strRemain; } return(cmd); } finally { _buildingSchema = false; } } #endif } else if (n == 6 || n == 5) // Locked -- delay a small amount before retrying { // Keep trying if (rnd == null) // First time we've encountered the lock { rnd = new Random(); } // If we've exceeded the command's timeout, give up and throw an error if ((uint)Environment.TickCount - starttick > timeoutMS) { throw new SqliteException(n, SQLiteLastError()); } else { // Otherwise sleep for a random amount of time up to 150ms System.Threading.Thread.CurrentThread.Join(rnd.Next(1, 150)); } } } if (n > 0) { throw new SqliteException(n, SQLiteLastError()); } strRemain = UTF8ToString(ptr, len); if (stmt != IntPtr.Zero) { cmd = new SqliteStatement(this, stmt, strSql.Substring(0, strSql.Length - strRemain.Length), previous); } return(cmd); } finally { handle.Free(); } }
internal override SqliteStatement Prepare(string strSql, SqliteStatement previous, out string strRemain) { IntPtr stmt = IntPtr.Zero; IntPtr ptr = IntPtr.Zero; int n = 17; int retries = 0; byte[] b = ToUTF8(strSql); string typedefs = null; SqliteStatement cmd = null; GCHandle handle = GCHandle.Alloc(b, GCHandleType.Pinned); IntPtr psql = handle.AddrOfPinnedObject(); try { while (n == 17 && retries < 3) { try { n = UnsafeNativeMethods.sqlite3_prepare_v2(_sql, psql, b.Length - 1, out stmt, out ptr); } catch (EntryPointNotFoundException) { n = UnsafeNativeMethods.sqlite3_prepare(_sql, psql, b.Length - 1, out stmt, out ptr); } retries++; if (n == 1) { if (String.Compare(SqliteLastError(), "near \"TYPES\": syntax error", StringComparison.OrdinalIgnoreCase) == 0) { int pos = strSql.IndexOf(';'); if (pos == -1) { pos = strSql.Length - 1; } typedefs = strSql.Substring(0, pos + 1); strSql = strSql.Substring(pos + 1); strRemain = ""; while (cmd == null && strSql.Length > 0) { cmd = Prepare(strSql, previous, out strRemain); strSql = strRemain; } if (cmd != null) { cmd.SetTypes(typedefs); } return(cmd); } } } if (n > 0) { throw new SqliteException(n, SqliteLastError()); } strRemain = UTF8ToString(ptr); if (stmt != IntPtr.Zero) { cmd = new SqliteStatement(this, stmt, strSql.Substring(0, strSql.Length - strRemain.Length), previous); } return(cmd); } finally { handle.Free(); } }