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(SQLiteConnection cnn, string strSql, SQLiteStatement previous, uint timeoutMS, out string strRemain) { SQLiteStatement statement2; IntPtr zero = IntPtr.Zero; IntPtr ptrRemain = IntPtr.Zero; int nRemain = 0; int errorCode = 0x11; int num3 = 0; byte[] buffer = SQLiteConvert.ToUTF8(strSql); string typedefs = null; SQLiteStatement statement = null; Random random = null; uint tickCount = (uint)Environment.TickCount; GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned); IntPtr pSql = handle.AddrOfPinnedObject(); try { while ((((errorCode == 0x11) || (errorCode == 6)) || (errorCode == 5)) && (num3 < 3)) { errorCode = UnsafeNativeMethods.sqlite3_prepare_interop((IntPtr)this._sql, pSql, buffer.Length - 1, out zero, out ptrRemain, out nRemain); if (errorCode == 0x11) { num3++; } else { if (errorCode == 1) { if (string.Compare(this.SQLiteLastError(), "near \"TYPES\": syntax error", StringComparison.OrdinalIgnoreCase) == 0) { int index = strSql.IndexOf(';'); if (index == -1) { index = strSql.Length - 1; } typedefs = strSql.Substring(0, index + 1); strSql = strSql.Substring(index + 1); strRemain = ""; while ((statement == null) && (strSql.Length > 0)) { statement = this.Prepare(cnn, strSql, previous, timeoutMS, out strRemain); strSql = strRemain; } if (statement != null) { statement.SetTypes(typedefs); } return(statement); } if (this._buildingSchema || (string.Compare(this.SQLiteLastError(), 0, "no such table: TEMP.SCHEMA", 0, 0x1a, StringComparison.OrdinalIgnoreCase) != 0)) { continue; } strRemain = ""; this._buildingSchema = true; try { ISQLiteSchemaExtensions service = ((IServiceProvider)SQLiteFactory.Instance).GetService(typeof(ISQLiteSchemaExtensions)) as ISQLiteSchemaExtensions; if (service != null) { service.BuildTempSchema(cnn); } while ((statement == null) && (strSql.Length > 0)) { statement = this.Prepare(cnn, strSql, previous, timeoutMS, out strRemain); strSql = strRemain; } return(statement); } finally { this._buildingSchema = false; } } switch (errorCode) { case 6: case 5: if (random == null) { random = new Random(); } if ((Environment.TickCount - tickCount) > timeoutMS) { throw new SQLiteException(errorCode, this.SQLiteLastError()); } Thread.Sleep(random.Next(1, 150)); break; } } } if (errorCode > 0) { throw new SQLiteException(errorCode, this.SQLiteLastError()); } strRemain = SQLiteConvert.UTF8ToString(ptrRemain, nRemain); if (zero != IntPtr.Zero) { statement = new SQLiteStatement(this, zero, strSql.Substring(0, strSql.Length - strRemain.Length), previous); } statement2 = statement; } finally { handle.Free(); } return(statement2); }