public static byte GetSafetyLevel(string z, int omitFull, byte dflt) { if (char.IsDigit(z[0])) { return((byte)ConvertEx.Atoi(z)); } int n = z.Length; for (int i = 0; i < _safetyLevelLength.Length - omitFull; i++) { if (_safetyLevelLength[i] == n && string.CompareOrdinal(_safetyLevelText.Substring(_safetyLevelOffset[i]), 0, z, 0, n) == 0) { return(_safetyLevelValue[i]); } } return(dflt); }
public static bool InitCallback(object init, int argc, string[] argv, object notUsed1) { InitData data = (InitData)init; Context ctx = data.Ctx; int db = data.Db; Debug.Assert(argc == 3); Debug.Assert(MutexEx.Held(ctx.Mutex)); E.DbClearProperty(ctx, db, SCHEMA.Empty); if (ctx.MallocFailed) { CorruptSchema(data, argv[0], null); return(true); } Debug.Assert(db >= 0 && db < ctx.DBs.length); if (argv == null) { return(false); // Might happen if EMPTY_RESULT_CALLBACKS are on */ } if (argv[1] == null) { CorruptSchema(data, argv[0], null); } else if (!string.IsNullOrEmpty(argv[2])) { // Call the parser to process a CREATE TABLE, INDEX or VIEW. But because ctx->init.busy is set to 1, no VDBE code is generated // or executed. All the parser does is build the internal data structures that describe the table, index, or view. Debug.Assert(ctx.Init.Busy); ctx.Init.DB = (byte)db; ctx.Init.NewTid = ConvertEx.Atoi(argv[1]); ctx.Init.OrphanTrigger = false; Vdbe stmt = null; #if DEBUG int rcp = Prepare(ctx, argv[2], -1, ref stmt, null); #else Prepare(ctx, argv[2], -1, ref stmt, null); #endif RC rc = ctx.ErrCode; #if DEBUG Debug.Assert(((int)rc & 0xFF) == (rcp & 0xFF)); #endif ctx.Init.DB = 0; if (rc != RC.OK) { if (ctx.Init.OrphanTrigger) { Debug.Assert(db == 1); } else { data.RC = rc; if (rc == RC.NOMEM) { ctx.MallocFailed = true; } else if (rc != RC.INTERRUPT && (RC)((int)rc & 0xFF) != RC.LOCKED) { CorruptSchema(data, argv[0], sqlite3_errmsg(ctx)); } } } stmt.Finalize(); } else if (argv[0] == null) { CorruptSchema(data, null, null); } else { // If the SQL column is blank it means this is an index that was created to be the PRIMARY KEY or to fulfill a UNIQUE // constraint for a CREATE TABLE. The index should have already been created when we processed the CREATE TABLE. All we have // to do here is record the root page number for that index. Index index = Parse.FindIndex(ctx, argv[0], ctx.DBs[db].Name); if (index == null) { // This can occur if there exists an index on a TEMP table which has the same name as another index on a permanent index. Since // the permanent table is hidden by the TEMP table, we can also safely ignore the index on the permanent table. // Do Nothing } else if (!ConvertEx.Atoi(argv[1], ref index.Id)) { CorruptSchema(data, argv[0], "invalid rootpage"); } } return(false); }
public string ExpandSql(string rawSql) { Context ctx = Ctx; // The database connection TextBuilder b = new TextBuilder(); // Accumulate the _output here TextBuilder.Init(b, 100, ctx.Limits[(int)LIMIT.LENGTH]); b.Tag = ctx; int rawSqlIdx = 0; int nextIndex = 1; // Index of next ? host parameter int idx = 0; // Index of a host parameter if (ctx.VdbeExecCnt > 1) { while (rawSqlIdx < rawSql.Length) { while (rawSql[rawSqlIdx++] != '\n' && rawSqlIdx < rawSql.Length) { ; } b.Append("-- ", 3); b.Append(rawSql, (int)rawSqlIdx); } } else { while (rawSqlIdx < rawSql.Length) { int tokenLength = 0; // Length of the parameter token int n = FindNextHostParameter(rawSql, rawSqlIdx, ref tokenLength); // Length of a token prefix Debug.Assert(n > 0); b.Append(rawSql.Substring(rawSqlIdx, n), n); rawSqlIdx += n; Debug.Assert(rawSqlIdx < rawSql.Length || tokenLength == 0); if (tokenLength == 0) { break; } if (rawSql[rawSqlIdx] == '?') { if (tokenLength > 1) { Debug.Assert(char.IsDigit(rawSql[rawSqlIdx + 1])); ConvertEx.Atoi(rawSql, rawSqlIdx + 1, ref idx); } else { idx = nextIndex; } } else { Debug.Assert(rawSql[rawSqlIdx] == ':' || rawSql[rawSqlIdx] == '$' || rawSql[rawSqlIdx] == '@'); C.ASSERTCOVERAGE(rawSql[rawSqlIdx] == ':'); C.ASSERTCOVERAGE(rawSql[rawSqlIdx] == '$'); C.ASSERTCOVERAGE(rawSql[rawSqlIdx] == '@'); idx = ParameterIndex(this, rawSql.Substring(rawSqlIdx, tokenLength), tokenLength); Debug.Assert(idx > 0); } rawSqlIdx += tokenLength; nextIndex = idx + 1; Debug.Assert(idx > 0 && idx <= Vars.length); Mem var = Vars[idx - 1]; // Value of a host parameter if ((var.Flags & MEM.Null) != 0) { b.Append("NULL", 4); } else if ((var.Flags & MEM.Int) != 0) { b.AppendFormat("%lld", var.u.I); } else if ((var.Flags & MEM.Real) != 0) { b.AppendFormat("%!.15g", var.R); } else if ((var.Flags & MEM.Str) != 0) { #if !OMIT_UTF16 TEXTENCODE encode = E.CTXENCODE(ctx); if (encode != TEXTENCODE.UTF8) { Mem utf8; //C._memset(&utf8, 0, sizeof(utf8)); utf8.Ctx = ctx; MemSetStr(utf8, var.Z, var.N, encode, C.DESTRUCTOR_STATIC); ChangeEncoding(utf8, TEXTENCODE.UTF8); b.AppendFormat("'%.*q'", utf8.N, utf8.Z); MemRelease(utf8); } else #endif b.AppendFormat("'%.*q'", var.N, var.Z); } else if ((var.Flags & MEM.Zero) != 0) { b.AppendFormat("zeroblob(%d)", var.u.Zeros); } else { Debug.Assert((var.Flags & MEM.Blob) != 0); b.Append("x'", 2); for (int i = 0; i < var.N; i++) { b.AppendFormat("%02x", var.u.Zeros[i] & 0xff); } b.Append("'", 1); } } } return(b.ToString()); }