示例#1
0
 static KeyInfo KeyInfoFromExprList(Parse parse, ExprList list)
 {
     Context ctx = parse.Ctx;
     int exprs = list.Exprs;
     KeyInfo info = new KeyInfo();
     if (info != null)
     {
         info.SortOrders = new SO[exprs];
         info.Colls = new CollSeq[exprs];
         info.Fields = (ushort)exprs;
         info.Encode = E.CTXENCODE(ctx);
         info.Ctx = ctx;
         int i;
         ExprList.ExprListItem item;
         for (i = 0; i < exprs; i++)
         {
             item = list.Ids[i];
             CollSeq coll = item.Expr.CollSeq(parse);
             if (coll == null)
                 coll = ctx.DefaultColl;
             info.Colls[i] = coll;
             info.SortOrders[i] = item.SortOrder;
         }
     }
     return info;
 }
示例#2
0
文件: Btree.cs 项目: BclEx/GpuStructs
        static RC btreeCursor(Btree p, Pid tableID, bool wrFlag, KeyInfo keyInfo, BtCursor cur)
        {
            var bt = p.Bt; // Shared b-tree handle

            Debug.Assert(p.HoldsMutex());

            // The following assert statements verify that if this is a sharable b-tree database, the connection is holding the required table locks, 
            // and that no other connection has any open cursor that conflicts with this lock.
            Debug.Assert(hasSharedCacheTableLock(p, (uint)tableID, keyInfo != null, (LOCK)(wrFlag ? 1 : 0) + 1));
            Debug.Assert(!wrFlag || !hasReadConflicts(p, (uint)tableID));

            // Assert that the caller has opened the required transaction.
            Debug.Assert(p.InTrans > TRANS.NONE);
            Debug.Assert(!wrFlag || p.InTrans == TRANS.WRITE);
            Debug.Assert(bt.Page1 != null && bt.Page1.Data != null);

            if (C._NEVER(wrFlag && (bt.BtsFlags & BTS.READ_ONLY) != 0))
                return RC.READONLY;
            if (tableID == 1 && btreePagecount(bt) == 0)
            {
                Debug.Assert(!wrFlag);
                tableID = 0;
            }

            // Now that no other errors can occur, finish filling in the BtCursor variables and link the cursor into the BtShared list.
            cur.RootID = tableID;
            cur.ID = -1;
            cur.KeyInfo = keyInfo;
            cur.Btree = p;
            cur.Bt = bt;
            cur.WrFlag = wrFlag;
            cur.Next = bt.Cursor;
            if (cur.Next != null)
                cur.Next.Prev = cur;
            bt.Cursor = cur;
            cur.State = CURSOR.INVALID;
            cur.CachedRowID = 0;
            return RC.OK;
        }
示例#3
0
文件: Btree.cs 项目: BclEx/GpuStructs
 public RC Cursor(Pid tableID, bool wrFlag, KeyInfo keyInfo, BtCursor cur)
 {
     Enter();
     var rc = btreeCursor(this, tableID, wrFlag, keyInfo, cur);
     Leave();
     return rc;
 }
示例#4
0
        static void FKLookupParent(Parse parse, int db, Table table, Index index, FKey fkey, int[] cols, int regDataId, int incr, bool isIgnore)
        {
            Vdbe v     = parse.GetVdbe(); // Vdbe to add code to
            int  curId = parse.Tabs - 1;  // Cursor number to use
            int  okId  = v.MakeLabel();   // jump here if parent key found

            // If nIncr is less than zero, then check at runtime if there are any outstanding constraints to resolve. If there are not, there is no need
            // to check if deleting this row resolves any outstanding violations.
            //
            // Check if any of the key columns in the child table row are NULL. If any are, then the constraint is considered satisfied. No need to
            // search for a matching row in the parent table.
            int i;

            if (incr < 0)
            {
                v.AddOp2(OP.FkIfZero, fkey.IsDeferred, okId);
            }
            for (i = 0; i < fkey.Cols.length; i++)
            {
                int regId = cols[i] + regDataId + 1;
                v.AddOp2(OP.IsNull, regId, okId);
            }

            if (!isIgnore)
            {
                if (index == null)
                {
                    // If pIdx is NULL, then the parent key is the INTEGER PRIMARY KEY column of the parent table (table pTab).
                    int mustBeIntId; // Address of MustBeInt instruction
                    int regTempId = parse.GetTempReg();

                    // Invoke MustBeInt to coerce the child key value to an integer (i.e. apply the affinity of the parent key). If this fails, then there
                    // is no matching parent key. Before using MustBeInt, make a copy of the value. Otherwise, the value inserted into the child key column
                    // will have INTEGER affinity applied to it, which may not be correct.
                    v.AddOp2(OP.SCopy, cols[0] + 1 + regDataId, regTempId);
                    mustBeIntId = v.AddOp2(OP.MustBeInt, regTempId, 0);

                    // If the parent table is the same as the child table, and we are about to increment the constraint-counter (i.e. this is an INSERT operation),
                    // then check if the row being inserted matches itself. If so, do not increment the constraint-counter.
                    if (table == fkey.From && incr == 1)
                    {
                        v.AddOp3(OP.Eq, regDataId, okId, regTempId);
                    }

                    parse.OpenTable(parse, curId, db, table, OP.OpenRead);
                    v.AddOp3(OP.NotExists, curId, 0, regTempId);
                    v.AddOp2(OP.Goto, 0, okId);
                    v.JumpHere(v.CurrentAddr() - 2);
                    v.JumpHere(mustBeIntId);
                    parse.ReleaseTempReg(regTempId);
                }
                else
                {
                    int     colsLength = fkey.Cols.length;
                    int     regTempId  = parse.GetTempRange(colsLength);
                    int     regRecId   = parse.GetTempReg();
                    KeyInfo key        = IndexKeyinfo(parse, index);

                    v.AddOp3(OP.OpenRead, curId, index.Id, db);
                    v.ChangeP4(v, -1, key, Vdbe.P4T.KEYINFO_HANDOFF);
                    for (i = 0; i < colsLength; i++)
                    {
                        v.AddOp2(OP.Copy, cols[i] + 1 + regDataId, regTempId + i);
                    }

                    // If the parent table is the same as the child table, and we are about to increment the constraint-counter (i.e. this is an INSERT operation),
                    // then check if the row being inserted matches itself. If so, do not increment the constraint-counter.

                    // If any of the parent-key values are NULL, then the row cannot match itself. So set JUMPIFNULL to make sure we do the OP_Found if any
                    // of the parent-key values are NULL (at this point it is known that none of the child key values are).
                    if (table == fkey.From && incr == 1)
                    {
                        int jumpId = v.CurrentAddr() + colsLength + 1;
                        for (i = 0; i < colsLength; i++)
                        {
                            int childId  = cols[i] + 1 + regDataId;
                            int parentId = index.Columns[i] + 1 + regDataId;
                            Debug.Assert(cols[i] != table.PKey);
                            if (index.Columns[i] == table.PKey)
                            {
                                parentId = regDataId;  // The parent key is a composite key that includes the IPK column
                            }
                            v.AddOp3(OP.Ne, childId, jumpId, parentId);
                            v.ChangeP5(SQLITE_JUMPIFNULL);
                        }
                        v.AddOp2(OP.Goto, 0, okId);
                    }

                    v.AddOp3(OP.MakeRecord, regTempId, colsLength, regRecId);
                    v.ChangeP4(-1, IndexAffinityStr(v, index), Vdbe.P4T.TRANSIENT);
                    v.AddOp4Int(OP.Found, curId, okId, regRecId, 0);

                    parse.ReleaseTempReg(regRecId);
                    parse.ReleaseTempRange(regTempId, colsLength);
                }
            }

            if (!fkey.IsDeferred && parse.Toplevel == null && parse.IsMultiWrite == 0)
            {
                // Special case: If this is an INSERT statement that will insert exactly one row into the table, raise a constraint immediately instead of
                // incrementing a counter. This is necessary as the VM code is being generated for will not open a statement transaction.
                Debug.Assert(incr == 1);
                HaltConstraint(parse, OE.Abort, "foreign key constraint failed", Vdbe.P4T.STATIC);
            }
            else
            {
                if (incr > 0 && !fkey.IsDeferred)
                {
                    E.Parse_Toplevel(parse).MayAbort = true;
                }
                v.AddOp2(OP.FkCounter, fkey.IsDeferred, incr);
            }

            v.ResolveLabel(v, okId);
            v.AddOp1(OP.Close, curId);
        }
示例#5
0
            internal MemPage[] Pages = new MemPage[BTCURSOR_MAX_DEPTH]; // Pages from root to current page
            internal void memset()
            {
                Next = Prev = null;
                KeyInfo = null;
                RootID = 0;
                CachedRowID = 0;
                Info = new CellInfo();
                WrFlag = false;
                AtLast = 0;
                ValidNKey = false;
                State = 0;
                KeyLength = 0;
                Key = null;
                SkipNext = 0;
#if !OMIT_INCRBLOB
                IsIncrblobHandle = false;
                Overflows = null;
#endif
                ID = 0;
            }
示例#6
0
 UnpackedRecord Vdbe_AllocUnpackedRecord(KeyInfo keyInfo, byte[] space, int spaceLength, out object free);
示例#7
0
 void Vdbe_RecordUnpack(KeyInfo keyInfo, int keyLength, byte[] key, UnpackedRecord p);
示例#8
0
 public void ChangeP4(int addr, P4_t p4, int n)
 {
     Debug.Assert(Magic == VDBE_MAGIC_INIT);
     Context ctx = Ctx;
     if (Ops.data == null || ctx.MallocFailed)
     {
         if (n != (int)P4T.KEYINFO && n != (int)P4T.VTAB)
             FreeP4(ctx, (P4T)n, p4);
         return;
     }
     Debug.Assert(Ops.length > 0);
     Debug.Assert(addr < Ops.length);
     if (addr < 0)
         addr = Ops.length - 1;
     VdbeOp op = Ops[addr];
     FreeP4(ctx, op.P4Type, op.P4.P);
     op.P4.P = null;
     if (n == (int)P4T.INT32)
     {
         // Note: this cast is safe, because the origin data point was an int that was cast to a (string ).
         op.P4.I = p4.I; //: PTR_TO_INT(p4);
         op.P4Type = P4T.INT32;
     }
     else if (n == (int)P4T.INT64)
     {
         op.P4.I64 = p4.I64;
         op.P4Type = (P4T)n;
     }
     else if (n == (int)P4T.REAL)
     {
         op.P4.Real = p4.Real;
         op.P4Type = (P4T)n;
     }
     else if (p4 == null)
     {
         op.P4.P = null;
         op.P4Type = P4T.NOTUSED;
     }
     else if (n == (int)P4T.KEYINFO)
     {
         int fields = p4.KeyInfo.Fields;
         KeyInfo keyInfo = new KeyInfo();
         op.P4.KeyInfo = keyInfo;
         if (keyInfo != null)
         {
             keyInfo = p4.KeyInfo._memcpy();
             op.P4Type = P4T.KEYINFO;
         }
         else
         {
             ctx.MallocFailed = true;
             op.P4Type = P4T.NOTUSED;
         }
     }
     else if (n == (int)P4T.KEYINFO_HANDOFF)
     {
         op.P4.KeyInfo = p4.KeyInfo;
         op.P4Type = P4T.KEYINFO;
     }
     else if (n == (int)P4T.FUNCDEF)
     {
         op.P4.Func = p4.Func;
         op.P4Type = P4T.FUNCDEF;
     }
     else if (n == (int)P4T.COLLSEQ)
     {
         op.P4.Coll = p4.Coll;
         op.P4Type = P4T.COLLSEQ;
     }
     else if (n == (int)P4T.DYNAMIC || n == (int)P4T.STATIC || n == (int)P4T.MPRINTF)
     {
         op.P4.Z = p4.Z;
         op.P4Type = P4T.DYNAMIC;
     }
     else if (n == (int)P4T.MEM)
     {
         op.P4.Mem = p4.Mem;
         op.P4Type = P4T.MEM;
     }
     else if (n == (int)P4T.INTARRAY)
     {
         op.P4.Is = p4.Is;
         op.P4Type = P4T.INTARRAY;
     }
     else if (n == (int)P4T.SUBPROGRAM)
     {
         op.P4.Program = p4.Program;
         op.P4Type = P4T.SUBPROGRAM;
     }
     else if (n == (int)P4T.VTAB)
     {
         op.P4.VTable = p4.VTable;
         op.P4Type = P4T.VTAB;
         p4.VTable.Lock();
         Debug.Assert(p4.VTable.Ctx == ctx);
     }
     else if (n < 0)
     {
         op.P4.P = p4.P;
         op.P4Type = (P4T)n;
     }
     else
     {
         //: if (n == 0) n = _strlen30(p4);
         op.P4.Z = p4.Z;
         op.P4Type = P4T.DYNAMIC;
     }
 }
示例#9
0
 public void ChangeP4(int addr, int i, int n) { ChangeP4(addr, new P4_t { I = i }, n); } // P4_INT32
 public void ChangeP4(int addr, KeyInfo keyInfo, int n) { ChangeP4(addr, new P4_t { KeyInfo = keyInfo }, n); } // P4T_KEYINFO
示例#10
0
 public static void RecordUnpack(KeyInfo keyInfo, int keyLength, byte[] key, UnpackedRecord p)
 {
     byte[] keys = key;
     Mem mem;
     p.Flags = 0;
     //: Debug.Assert(C._HASALIGNMENT8(mem));
     int szHdr;
     uint idx = (uint)ConvertEx.GetVarint32(keys, 0, out szHdr);
     int d = szHdr;
     ushort u = 0; // Unsigned loop counter
     while (idx < szHdr && u < p.Fields && d <= keyLength)
     {
         p.Mems[u] = mem = C._alloc(p.Mems[u]);
         uint serialType;
         idx += (uint)ConvertEx.GetVarint32(keys, idx, out serialType);
         mem.Encode = keyInfo.Encode;
         mem.Ctx = (Context)keyInfo.Ctx;
         //mem->Flags = 0; // sqlite3VdbeSerialGet() will set this for us
         //: mem.Malloc = null;
         d += (int)SerialGet(keys, d, serialType, mem);
         u++;
     }
     Debug.Assert(u <= keyInfo.Fields + 1);
     p.Fields = (ushort)u;
 }
示例#11
0
 public static UnpackedRecord AllocUnpackedRecord(KeyInfo keyInfo)
 {
     var p = new UnpackedRecord();
     p.Mems = new Mem[p.Fields + 1];
     p.KeyInfo = keyInfo;
     p.Fields = (ushort)(keyInfo.Fields + 1);
     return p;
 }
示例#12
0
 public int AddOp4(OP op, int p1, int p2, int p3, KeyInfo p4, Vdbe.P4T p4t) // KeyInfo
 {
     int addr = AddOp3(op, p1, p2, p3);
     ChangeP4(addr, new P4_t { KeyInfo = p4 }, p4t);
     return addr;
 }