public RowEnumerator(TableSnapshot <TRecord> table)
 {
     this.table   = table;
     this.version = this.table.StoreSnapshot.Version;
     this.count   = this.table.table.Count(this.version);
     this.index   = -1;
 }
示例#2
0
 /// <summary>
 /// Pushes row to log. Row can be logged only once in transaction, so only initial state (as it was at the beginning of transaction) will be saved
 /// </summary>
 /// <param name="row">Reference to the data to be logged</param>
 /// <param name="rowId">Id of this data. This should be the Id of row provided in the first param.</param>
 private void PushToLog(ref Row row, RowId rowId)
 {
     // ref to row should be in table at rowId. It is impossible to check this in C#, so just check if bits are equal
     Debug.Assert(
         0 == TableSnapshot <TRecord> .Compare(
             this.Fields, ref row.Data, ref this.table.ItemAddress(rowId.Value).Page[this.table.ItemAddress(rowId.Value).Index].Data
             ),
         "ref to row should be in table at rowId"
         );
     ValueList <Snap> .Address snapAddress = this.snap.ItemAddress(this.snap.Count - 1);
     if (snapAddress.Page[snapAddress.Index].Version < this.SnapStore.Version)
     {
         // first change in this transaction so the row is older
         Debug.Assert(rowId.Value < snapAddress.Page[snapAddress.Index].TableSize, "Row should be already in the table");
         this.snap.PrepareAdd();
         this.log.PrepareAdd();
         Snap point = new Snap()
         {
             Version   = this.SnapStore.Version,
             TableSize = this.table.Count,
             LogSize   = this.log.Count + 1
         };
         RuntimeHelpers.PrepareConstrainedRegions();
         try {} finally {
             int index = this.log.FixedAllocate();
             ValueList <Log> .Address logAddress = this.log.ItemAddress(index);
             logAddress.Page[logAddress.Index].Data        = row.Data;
             logAddress.Page[logAddress.Index].RowId       = rowId;
             logAddress.Page[logAddress.Index].RawLogIndex = row.RawLogIndex;
             row.LogIndex = index;
             this.snap.FixedAdd(ref point);
         }
     }
     else
     {
         Debug.Assert(snapAddress.Page[snapAddress.Index].Version == this.SnapStore.Version, "Impossible state: this should be the current transaction");
         Debug.Assert(snapAddress.Page[snapAddress.Index].TableSize == this.table.Count, "Impossible state: wrong table size");
         Debug.Assert(snapAddress.Page[snapAddress.Index].LogSize == this.log.Count, "Impossible state: wrong log size");
         // some changes were made in this transaction. Check if the row was already modified in this transaction.
         // get size of log in the previous transaction
         ValueList <Snap> .Address oldSnapAddress = this.snap.ItemAddress(this.snap.Count - 2);
         if (rowId.Value < oldSnapAddress.Page[oldSnapAddress.Index].TableSize && row.LogIndex < oldSnapAddress.Page[oldSnapAddress.Index].LogSize)
         {
             // this is the first time the row is updated in this transaction
             Debug.Assert(snapAddress.Page[snapAddress.Index].LogSize == this.log.Count, "Invalid state: wrong log size");
             this.log.PrepareAdd();
             RuntimeHelpers.PrepareConstrainedRegions();
             try {} finally {
                 int index = this.log.FixedAllocate();
                 ValueList <Log> .Address logAddress = this.log.ItemAddress(index);
                 logAddress.Page[logAddress.Index].Data        = row.Data;
                 logAddress.Page[logAddress.Index].RowId       = rowId;
                 logAddress.Page[logAddress.Index].RawLogIndex = row.RawLogIndex;
                 row.LogIndex = index;
                 snapAddress.Page[snapAddress.Index].LogSize = this.log.Count;
             }
         }
     }
 }
 public ChangeEnumerator(TableSnapshot <TRecord> table, List <int> version)
 {
     // assuming version is sorted
     this.table      = table.table;
     this.newVersion = version[version.Count - 1];
     this.oldVersion = version[0];
     this.MergeChanges(version);
     this.enumerator = this.action.GetEnumerator();
 }
 public ForeignKey(
     string name, IUniqueIndex <TField> primaryKey, TableSnapshot <TRecord> childTable, IField <TRecord, TField> childColumn, ForeignKeyAction action, bool allowsDefault
     )
 {
     this.Name          = name;
     this.primaryKey    = primaryKey;
     this.childTable    = childTable;
     this.childColumn   = childColumn;
     this.action        = action;
     this.allowsDefault = allowsDefault;
 }
示例#5
0
        /// <summary>
        /// Sets entire structure.
        /// </summary>
        /// <param name="rowId"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public bool SetData(RowId rowId, ref TRecord data)
        {
            Debug.Assert(0 <= rowId.Value && rowId.Value < this.table.Count, "broken rowId");
            this.ValidateModification();
            ValueList <Row> .Address address = this.table.ItemAddress(rowId.Value);
            SnapTable <TRecord> .ValidateModification(ref address);

            if (TableSnapshot <TRecord> .Compare(this.Fields, ref address.Page[address.Index].Data, ref data) != 0)
            {
                this.PushToLog(ref address.Page[address.Index], rowId);
                address.Page[address.Index].Data = data;
                Debug.Assert(TableSnapshot <TRecord> .Compare(this.Fields, ref address.Page[address.Index].Data, ref data) == 0, "Assignment or comparison failed");
                return(true);
            }
            return(false);
        }
        private void DeleteRow(RowId rowId)
        {
            int timestamp = TableSnapshot <TRecord> .Timestamp();

            foreach (List <IIndex <TRecord> > list in this.table.Indexes)
            {
                if (list != null)
                {
                    foreach (IIndex <TRecord> index in list)
                    {
                        if (index.Timestamp != timestamp)
                        {
                            index.Delete(rowId);
                            index.Timestamp = timestamp;
                        }
                    }
                }
            }
            this.table.Delete(rowId);
        }
 /// <summary>
 /// Checks if table is empty i.e. no records exist.
 /// </summary>
 /// <returns></returns>
 public bool IsEmpty()
 {
     foreach (List <IIndex <TRecord> > list in this.table.Indexes)
     {
         if (list != null && 0 < list.Count)
         {
             foreach (IIndex <TRecord> index in list)
             {
                 return(index.IsEmpty(this.StoreSnapshot.Version));
             }
         }
     }
     if (this.table.PrimaryKey != null)
     {
         // No real index were found. The only hope is pseudo unique index of primary key.
         // Right now it is not faster then just table scan, but anyway use it as in the future it may change.
         return(this.table.PrimaryKey.IsEmpty(this.StoreSnapshot.Version));
     }
     // There is no indexes on the table. Do a full scan.
     return(TableSnapshot <TRecord> .IsEmpty(this.table, this.StoreSnapshot.Version));
 }
        public RowId Insert(ref TRecord data)
        {
            this.ValidateModification();
            RowId rowId     = this.table.Insert(ref data);
            int   timestamp = TableSnapshot <TRecord> .Timestamp();

            foreach (List <IIndex <TRecord> > list in this.table.Indexes)
            {
                if (list != null)
                {
                    foreach (IIndex <TRecord> index in list)
                    {
                        if (index.Timestamp != timestamp)
                        {
                            index.Insert(rowId);
                            index.Timestamp = timestamp;
                        }
                    }
                }
            }
            return(rowId);
        }
示例#9
0
 public bool IsEmpty(int version)
 {
     return(TableSnapshot <TRecord> .IsEmpty(this.table, version));
 }
 public RolledBackChangesEnumerator(TableSnapshot <TRecord> table, int version)
 {
     this.enumerator = table.table.GetRolledBackChanges(version);
 }