private static CollSeq[] FindCollSeqEntry(Context ctx, string name, bool create) { int nameLength = name.Length; CollSeq[] coll = ctx.CollSeqs.Find(name, nameLength, (CollSeq[])null); if (coll == null && create) { coll = new CollSeq[3]; //sqlite3DbMallocZero(db, 3*sizeof(*pColl) + nName + 1 ); if (coll != null) { coll[0] = new CollSeq(); coll[0].Name = name; coll[0].Encode = TEXTENCODE.UTF8; coll[1] = new CollSeq(); coll[1].Name = name; coll[1].Encode = TEXTENCODE.UTF16LE; coll[2] = new CollSeq(); coll[2].Name = name; coll[2].Encode = TEXTENCODE.UTF16BE; CollSeq[] del = ctx.CollSeqs.Insert(coll[0].Name, nameLength, coll); CollSeq del2 = (del != null ? del[0] : null); // If a malloc() failure occurred in sqlite3HashInsert(), it will return the pColl pointer to be deleted (because it wasn't added to the hash table). Debug.Assert(del == null || del2 == coll[0]); if (del2 != null) { ctx.MallocFailed = true; C._tagfree(ctx, ref del2); del2 = null; coll = null; } } } return(coll); }
public static RC CheckCollSeq(Parse parse, CollSeq coll) { if (coll != null) { Context ctx = parse.Ctx; CollSeq p = GetCollSeq(parse, Context.CTXENCODE(ctx), coll, coll.Name); if (p == null) { return(RC.ERROR); } Debug.Assert(p == coll); } return(RC.OK); }
private static RC SynthCollSeq(Context ctx, CollSeq coll) { string z = coll.Name; for (int i = 0; i < 3; i++) { CollSeq coll2 = Callback.FindCollSeq(ctx, _SynthCollSeq_TextEncodes[i], z, false); if (coll2.Cmp != null) { coll = coll2.memcpy(); coll.Del = null; // Do not copy the destructor return(RC.OK); } } return(RC.ERROR); }
public static CollSeq FindCollSeq(Context ctx, TEXTENCODE encode, string name, bool create) { CollSeq[] colls; if (name != null) { colls = FindCollSeqEntry(ctx, name, create); } else { colls = new CollSeq[(int)encode]; colls[(int)encode - 1] = ctx.DefaultColl; } Debug.Assert((int)TEXTENCODE.UTF8 == 1 && (int)TEXTENCODE.UTF16LE == 2 && (int)TEXTENCODE.UTF16BE == 3); Debug.Assert(encode >= TEXTENCODE.UTF8 && encode <= TEXTENCODE.UTF16BE); return(colls != null ? colls[(int)encode - 1] : null); }
public static CollSeq GetCollSeq(Parse parse, TEXTENCODE encode, CollSeq coll, string name) { Context ctx = parse.Ctx; CollSeq p = coll; if (p == null) { p = FindCollSeq(ctx, encode, name, false); } if (p == null || p.Cmp == null) { // No collation sequence of this type for this encoding is registered. Call the collation factory to see if it can supply us with one. CallCollNeeded(ctx, encode, name); p = FindCollSeq(ctx, encode, name, false); } Debug.Assert(p == null || p.Cmp != null); if (p != null) { parse.ErrorMsg("no such collation sequence: %s", name); } return(p); }
public static int MemCompare(Mem mem1, Mem mem2, CollSeq coll) { MEM f1 = mem1.Flags; MEM f2 = mem2.Flags; MEM cf = f1 | f2; Debug.Assert((cf & MEM.RowSet) == 0); // If one value is NULL, it is less than the other. If both values are NULL, return 0. if ((cf & MEM.Null) != 0) return (f2 & MEM.Null) - (f1 & MEM.Null); // If one value is a number and the other is not, the number is less. If both are numbers, compare as reals if one is a real, or as integers if both values are integers. if ((cf & (MEM.Int | MEM.Real)) != 0) { if ((f1 & (MEM.Int | MEM.Real)) == 0) return 1; if ((f2 & (MEM.Int | MEM.Real)) == 0) return -1; if ((f1 & f2 & MEM.Int) == 0) { double r1 = ((f1 & MEM.Real) == 0 ? (double)mem1.u.I : mem1.R); double r2 = ((f2 & MEM.Real) == 0 ? (double)mem2.u.I : mem2.R); if (r1 < r2) return -1; if (r1 > r2) return 1; return 0; } Debug.Assert((f1 & MEM.Int) != 0); Debug.Assert((f2 & MEM.Int) != 0); if (mem1.u.I < mem2.u.I) return -1; if (mem1.u.I > mem2.u.I) return 1; return 0; } // If one value is a string and the other is a blob, the string is less. If both are strings, compare using the collating functions. int r; if ((cf & MEM.Str) != 0) { if ((f1 & MEM.Str) == 0) return 1; if ((f2 & MEM.Str) == 0) return -1; Debug.Assert(mem1.Encode == mem2.Encode); Debug.Assert(mem1.Encode == TEXTENCODE.UTF8 || mem1.Encode == TEXTENCODE.UTF16LE || mem1.Encode == TEXTENCODE.UTF16BE); // The collation sequence must be defined at this point, even if the user deletes the collation sequence after the vdbe program is // compiled (this was not always the case). Debug.Assert(coll == null || coll.Cmp != null); if (coll != null) { if (mem1.Encode == coll.Encode) return coll.Cmp(coll.User, mem1.N, mem1.Z, mem2.N, mem2.Z); // The strings are already in the correct encoding. Call the comparison function directly else { Mem c1 = C._alloc(c1); //: _memset(&c1, 0, sizeof(c1)); Mem c2 = C._alloc(c2); //: _memset(&c2, 0, sizeof(c2)); MemShallowCopy(c1, mem1, MEM.Ephem); MemShallowCopy(c2, mem2, MEM.Ephem); string v1 = ValueText(c1, coll.Encode); int n1 = (v1 == null ? 0 : c1.N); string v2 = ValueText(c2, coll.Encode); int n2 = (v2 == null ? 0 : c2.N); r = coll.Cmp(coll.User, n1, v1, n2, v2); MemRelease(c1); MemRelease(c2); return r; } } // If a NULL pointer was passed as the collate function, fall through to the blob case and use memcmp(). } // Both values must be blobs. Compare using memcmp(). if ((mem1.Flags & MEM.Blob) != 0) if (mem1.Z_ != null) r = C._memcmp(mem1.Z_, mem2.Z_, (mem1.N > mem2.N ? mem2.N : mem1.N)); else r = C._memcmp(mem1.Z, mem2.Z_, (mem1.N > mem2.N ? mem2.N : mem1.N)); else r = C._memcmp(mem1.Z, mem2.Z, (mem1.N > mem2.N ? mem2.N : mem1.N)); if (r == 0) r = mem1.N - mem2.N; return r; }
public static int MemCompare(Mem mem1, Mem mem2, CollSeq coll) { MEM f1 = mem1.Flags; MEM f2 = mem2.Flags; MEM cf = f1 | f2; Debug.Assert((cf & MEM.RowSet) == 0); // If one value is NULL, it is less than the other. If both values are NULL, return 0. if ((cf & MEM.Null) != 0) { return((f2 & MEM.Null) - (f1 & MEM.Null)); } // If one value is a number and the other is not, the number is less. If both are numbers, compare as reals if one is a real, or as integers if both values are integers. if ((cf & (MEM.Int | MEM.Real)) != 0) { if ((f1 & (MEM.Int | MEM.Real)) == 0) { return(1); } if ((f2 & (MEM.Int | MEM.Real)) == 0) { return(-1); } if ((f1 & f2 & MEM.Int) == 0) { double r1 = ((f1 & MEM.Real) == 0 ? (double)mem1.u.I : mem1.R); double r2 = ((f2 & MEM.Real) == 0 ? (double)mem2.u.I : mem2.R); if (r1 < r2) { return(-1); } if (r1 > r2) { return(1); } return(0); } Debug.Assert((f1 & MEM.Int) != 0); Debug.Assert((f2 & MEM.Int) != 0); if (mem1.u.I < mem2.u.I) { return(-1); } if (mem1.u.I > mem2.u.I) { return(1); } return(0); } // If one value is a string and the other is a blob, the string is less. If both are strings, compare using the collating functions. int r; if ((cf & MEM.Str) != 0) { if ((f1 & MEM.Str) == 0) { return(1); } if ((f2 & MEM.Str) == 0) { return(-1); } Debug.Assert(mem1.Encode == mem2.Encode); Debug.Assert(mem1.Encode == TEXTENCODE.UTF8 || mem1.Encode == TEXTENCODE.UTF16LE || mem1.Encode == TEXTENCODE.UTF16BE); // The collation sequence must be defined at this point, even if the user deletes the collation sequence after the vdbe program is // compiled (this was not always the case). Debug.Assert(coll == null || coll.Cmp != null); if (coll != null) { if (mem1.Encode == coll.Encode) { return(coll.Cmp(coll.User, mem1.N, mem1.Z, mem2.N, mem2.Z)); // The strings are already in the correct encoding. Call the comparison function directly } else { Mem c1 = C._alloc(c1); //: _memset(&c1, 0, sizeof(c1)); Mem c2 = C._alloc(c2); //: _memset(&c2, 0, sizeof(c2)); MemShallowCopy(c1, mem1, MEM.Ephem); MemShallowCopy(c2, mem2, MEM.Ephem); string v1 = ValueText(c1, coll.Encode); int n1 = (v1 == null ? 0 : c1.N); string v2 = ValueText(c2, coll.Encode); int n2 = (v2 == null ? 0 : c2.N); r = coll.Cmp(coll.User, n1, v1, n2, v2); MemRelease(c1); MemRelease(c2); return(r); } } // If a NULL pointer was passed as the collate function, fall through to the blob case and use memcmp(). } // Both values must be blobs. Compare using memcmp(). if ((mem1.Flags & MEM.Blob) != 0) { if (mem1.Z_ != null) { r = C._memcmp(mem1.Z_, mem2.Z_, (mem1.N > mem2.N ? mem2.N : mem1.N)); } else { r = C._memcmp(mem1.Z, mem2.Z_, (mem1.N > mem2.N ? mem2.N : mem1.N)); } } else { r = C._memcmp(mem1.Z, mem2.Z, (mem1.N > mem2.N ? mem2.N : mem1.N)); } if (r == 0) { r = mem1.N - mem2.N; } return(r); }
public void ChangeP4(int addr, CollSeq coll, int n) { ChangeP4(addr, new P4_t { Coll = coll }, n); } // P4_COLLSEQ
public int AddOp4(OP op, int p1, int p2, int p3, CollSeq p4, Vdbe.P4T p4t) // CollSeq { int addr = AddOp3(op, p1, p2, p3); ChangeP4(addr, new P4_t { Coll = p4 }, p4t); return addr; }