static bool IsDate(FuncContext fctx, int argc, Mem[] argv, out DateTime p) { int i; string z; p = new DateTime(); if (argc == 0) SetDateTimeToCurrent(fctx, p); TYPE type; if ((type = Vdbe.Value_Type(argv[0])) == TYPE.FLOAT || type == TYPE.INTEGER) { p.JD = (long)(Vdbe.Value_Double(argv[0]) * 86400000.0 + 0.5); p.ValidJD = true; } else { z = Vdbe.Value_Text(argv[0]); if (z == null || ParseDateOrTime(fctx, z, ref p)) return true; } for (i = 1; i < argc; i++) { z = Vdbe.Value_Text(argv[i]); if (z == null || ParseModifier(fctx, z, p) != RC.OK) return true; } return false; }
static void RenameTriggerFunc(FuncContext fctx, int notUsed, Mem[] argv) { Context ctx = Vdbe.Context_Ctx(fctx); string sql = Vdbe.Value_Text(argv[0]); string tableName = Vdbe.Value_Text(argv[1]); int z = 0, zLoc = 0; int length = 1; TK token = 0; Token tname = new Token(); int dist = 3; // The principle used to locate the table name in the CREATE TRIGGER statement is that the table name is the first token that is immediatedly // preceded by either TK_ON or TK_DOT and immediatedly followed by one of TK_WHEN, TK_BEGIN or TK_FOR. if (sql != null) { return; } do { if (z == sql.Length) { return; // Ran out of input before finding the table name. Return NULL. } // Store the token that zCsr points to in tname. zLoc = z; tname.data = sql.Substring(z, length); tname.length = (uint)length; // Advance zCsr to the next token. Store that token type in 'token', and its length in 'len' (to be used next iteration of this loop). do { z += length; length = (z == sql.Length ? 1 : Parse.GetToken(sql, z, ref token)); } while (token == TK.SPACE); Debug.Assert(length > 0); // Variable 'dist' stores the number of tokens read since the most recent TK_DOT or TK_ON. This means that when a WHEN, FOR or BEGIN // token is read and 'dist' equals 2, the condition stated above to be met. // // Note that ON cannot be a database, table or column name, so there is no need to worry about syntax like // "CREATE TRIGGER ... ON ON.ON BEGIN ..." etc. dist++; if (token == TK.DOT || token == TK.ON) { dist = 0; } } while (dist != 2 || (token != TK.WHEN && token != TK.FOR && token != TK.BEGIN)); // Variable tname now contains the token that is the old table-name in the CREATE TRIGGER statement. string r = C._mtagprintf(ctx, "%.*s\"%w\"%s", zLoc, sql.Substring(0, zLoc), tableName, sql.Substring(zLoc + (int)tname.length)); Vdbe.Result_Text(fctx, r, -1, C.DESTRUCTOR_DYNAMIC); }
static void RenameParentFunc(FuncContext fctx, int notUsed, Mem[] argv) { Context ctx = Vdbe.Context_Ctx(fctx); string input = Vdbe.Value_Text(argv[0]); string oldName = Vdbe.Value_Text(argv[1]); string newName = Vdbe.Value_Text(argv[2]); int zIdx; // Pointer to token int zLeft = 0; // Pointer to remainder of String TK token = 0; // Type of token string output = string.Empty; int n; // Length of token z for (int z = 0; z < input.Length; z += n) { n = Parse.GetToken(input, z, ref token); if (token == TK.REFERENCES) { string parent; do { z += n; n = Parse.GetToken(input, z, ref token); } while (token == TK.SPACE); parent = (z + n < input.Length ? input.Substring(z, n) : string.Empty); if (string.IsNullOrEmpty(parent)) { break; } Parse.Dequote(ref parent); if (oldName.Equals(parent, StringComparison.OrdinalIgnoreCase)) { string out_ = C._mtagprintf(ctx, "%s%.*s\"%w\"", output, z - zLeft, input.Substring(zLeft), newName); C._tagfree(ctx, ref output); output = out_; z += n; zLeft = z; } C._tagfree(ctx, ref parent); } } string r = C._mtagprintf(ctx, "%s%s", output, input.Substring(zLeft)); Vdbe.Result_Text(fctx, r, -1, DESTRUCTOR.DYNAMIC); C._tagfree(ctx, ref output); }
static void RenameTableFunc(FuncContext fctx, int notUsed, Mem[] argv) { Context ctx = Vdbe.Context_Ctx(fctx); string sql = Vdbe.Value_Text(argv[0]); string tableName = Vdbe.Value_Text(argv[1]); if (string.IsNullOrEmpty(sql)) { return; } int length = 0; TK token = 0; Token tname = new Token(); int z = 0, zLoc = 0; // The principle used to locate the table name in the CREATE TABLE statement is that the table name is the first non-space token that // is immediately followed by a TK_LP or TK_USING token. do { if (z == sql.Length) { return; // Ran out of input before finding an opening bracket. Return NULL. } // Store the token that zCsr points to in tname. zLoc = z; tname.data = sql.Substring(z); tname.length = (uint)length; // Advance zCsr to the next token. Store that token type in 'token', and its length in 'len' (to be used next iteration of this loop). do { z += length; length = (z == sql.Length ? 1 : Parse.GetToken(sql, z, ref token)); } while (token == TK.SPACE); Debug.Assert(length > 0); } while (token != TK.LP && token != TK.USING); string r = C._mtagprintf(ctx, "%.*s\"%w\"%s", zLoc, sql.Substring(0, zLoc), tableName, sql.Substring(zLoc + (int)tname.length)); Vdbe.Result_Text(fctx, r, -1, DESTRUCTOR_DYNAMIC); }
static void StrftimeFunc(FuncContext fctx, int argc, Mem[] argv) { { DateTime x = new DateTime(); ulong n; int i, j; StringBuilder z; string fmt = Vdbe.Value_Text(argv[0]); StringBuilder zdtBuf = new StringBuilder(100); Mem[] argv1 = new Mem[argc - 1]; for (i = 0; i < argc - 1; i++) argv[i + 1]._memcpy(ref argv1[i]); if (fmt == null || IsDate(fctx, argc - 1, argv1, out x)) return; Context ctx = Vdbe.Context_Ctx(fctx); for (i = 0, n = 1; i < fmt.Length; i++, n++) { if (fmt[i] == '%') { switch ((char)fmt[i + 1]) { case 'd': case 'H': case 'm': case 'M': case 'S': case 'W': n++; break; // fall thru case 'w': case '%': break; case 'f': n += 8; break; case 'j': n += 3; break; case 'Y': n += 8; break; case 's': case 'J': n += 50; break; default: return; // ERROR. return a NULL } i++; } } C.ASSERTCOVERAGE(n == (ulong)(zdtBuf.Length - 1)); C.ASSERTCOVERAGE(n == (ulong)zdtBuf.Length); C.ASSERTCOVERAGE(n == (ulong)ctx.Limits[(int)LIMIT.LENGTH] + 1); C.ASSERTCOVERAGE(n == (ulong)ctx.Limits[(int)LIMIT.LENGTH]); if (n < (ulong)zdtBuf.Capacity) z = zdtBuf; else if (n > (ulong)ctx.Limits[(int)LIMIT.LENGTH]) { Vdbe.Result_ErrorOverflow(fctx); return; } else { z = new StringBuilder((int)n); if (z == null) { Vdbe.Result_ErrorNoMem(fctx); return; } } ComputeJD(x); ComputeYMD_HMS(x); for (i = j = 0; i < fmt.Length; i++) { if (fmt[i] != '%') z.Append((char)fmt[i]); else { i++; _zdtTemp.Length = 0; switch ((char)fmt[i]) { case 'd': C.__snprintf(_zdtTemp, 3, "%02d", x.D); z.Append(_zdtTemp); j += 2; break; case 'f': { double s = x.s; if (s > 59.999) s = 59.999; C.__snprintf(_zdtTemp, 7, "%06.3f", s); z.Append(_zdtTemp); j = z.Length; break; } case 'H': C.__snprintf(_zdtTemp, 3, "%02d", x.h); z.Append(_zdtTemp); j += 2; break; case 'W': // Fall thru case 'j': { DateTime y = new DateTime(); x.memcopy(y); y.ValidJD = false; y.M = 1; y.D = 1; ComputeJD(y); int days = (int)((x.JD - y.JD + 43200000) / 86400000); ; // Number of days since 1st day of year if (fmt[i] == 'W') { int wd = (int)(((x.JD + 43200000) / 86400000) % 7); // 0=Monday, 1=Tuesday, ... 6=Sunday C.__snprintf(_zdtTemp, 3, "%02d", (days + 7 - wd) / 7); z.Append(_zdtTemp); j += 2; } else { C.__snprintf(_zdtTemp, 4, "%03d", days + 1); z.Append(_zdtTemp); j += 3; } break; } case 'J': { C.__snprintf(_zdtTemp, 20, "%.16g", x.JD / 86400000.0); z.Append(_zdtTemp); j = z.Length; break; } case 'm': C.__snprintf(_zdtTemp, 3, "%02d", x.M); z.Append(_zdtTemp); j += 2; break; case 'M': C.__snprintf(_zdtTemp, 3, "%02d", x.m); z.Append(_zdtTemp); j += 2; break; case 's': { C.__snprintf(_zdtTemp, 30, "%lld", (long)(x.JD / 1000 - 210866760000L)); z.Append(_zdtTemp); j = z.Length; break; } case 'S': C.__snprintf(_zdtTemp, 3, "%02d", (int)x.s); z.Append(_zdtTemp); j += 2; break; case 'w': { z.Append((((x.JD + 129600000) / 86400000) % 7)); break; } case 'Y': { C.__snprintf(_zdtTemp, 5, "%04d", x.Y); z.Append(_zdtTemp); j = z.Length; break; } default: z.Append('%'); break; } } } Vdbe.Result_Text(fctx, z, -1, z == (zdtBuf ? DESTRUCTOR_TRANSIENT : DESTRUCTOR_DYNAMIC); } }