public PreparedArrayContainsComparison(IContext context, ArrayHandler arrayHandler
                                        , ITypeHandler4 typeHandler, object obj)
 {
     _arrayHandler       = arrayHandler;
     _preparedComparison = Handlers4.PrepareComparisonFor(typeHandler, context, obj);
     _container          = context.Transaction().Container();
 }
Exemple #2
0
        internal virtual int CompareKeys(IContext context, object key1, object key2)
        {
            IPreparedComparison preparedComparison = _keyHandler.PrepareComparison(context, key1
                                                                                   );

            return(preparedComparison.CompareTo(key2));
        }
 public PreparedArrayContainsComparison(IContext context, ArrayHandler arrayHandler
     , ITypeHandler4 typeHandler, object obj)
 {
     _arrayHandler = arrayHandler;
     _preparedComparison = Handlers4.PrepareComparisonFor(typeHandler, context, obj);
     _container = context.Transaction().Container();
 }
Exemple #4
0
 private int CompareInReadMode(Transaction trans, IPreparedComparison preparedComparison
                               , ByteArrayBuffer reader, int index)
 {
     SeekKey(reader, index);
     return(-preparedComparison.CompareTo(KeyHandler().ReadIndexEntry(trans.Context(),
                                                                      reader)));
 }
Exemple #5
0
 internal override void Unmarshall(Transaction trans)
 {
     if (i_trans != null)
     {
         return;
     }
     base.Unmarshall(trans);
     if (i_object == null)
     {
         _preparedComparison = Null.Instance;
     }
     if (i_classMetadataID != 0)
     {
         _classMetadata = trans.Container().ClassMetadataForID(i_classMetadataID);
     }
     if (i_field != null)
     {
         i_field.Unmarshall(trans);
     }
     if (i_objectID > 0)
     {
         object obj = trans.Container().TryGetByID(trans, i_objectID);
         if (obj != null)
         {
             i_object = obj;
         }
     }
 }
Exemple #6
0
 public void Remove(Transaction trans, IPreparedComparison preparedComparison, object
                    obj, int index)
 {
     if (Remove(trans, obj, index))
     {
         return;
     }
     // now we try if removal is OK for the next element in this node
     if (index != LastIndex())
     {
         if (CompareInWriteMode(preparedComparison, index + 1) != 0)
         {
             return;
         }
         Remove(trans, preparedComparison, obj, index + 1);
         return;
     }
     // nothing else worked so far, move on to the next node, try there
     Db4objects.Db4o.Internal.Btree.BTreeNode node = NextNode();
     if (node == null)
     {
         return;
     }
     node.PrepareWrite(trans);
     if (node.CompareInWriteMode(preparedComparison, 0) != 0)
     {
         return;
     }
     node.Remove(trans, preparedComparison, obj, 0);
 }
Exemple #7
0
        internal BTreeNodeSearchResult SearchLeaf(Transaction trans, IPreparedComparison
                                                  preparedComparison, SearchTarget target)
        {
            ByteArrayBuffer reader = PrepareRead(trans);
            Searcher        s      = Search(trans, preparedComparison, reader, target);

            if (!_isLeaf)
            {
                return(Child(reader, s.Cursor()).SearchLeaf(trans, preparedComparison, target));
            }
            if (!s.FoundMatch() || target == SearchTarget.Any || target == SearchTarget.Highest)
            {
                return(new BTreeNodeSearchResult(trans, reader, Btree(), s, this));
            }
            if (target == SearchTarget.Lowest)
            {
                BTreeNodeSearchResult res = FindLowestLeafMatch(trans, preparedComparison, s.Cursor
                                                                    () - 1);
                if (res != null)
                {
                    return(res);
                }
                return(CreateMatchingSearchResult(trans, reader, s.Cursor()));
            }
            throw new InvalidOperationException();
        }
Exemple #8
0
        private void AssertComparison(int expected, double prepareWith, double compareTo)
        {
            IPreparedComparison preparedComparison = _handler.PrepareComparison(Stream().Transaction
                                                                                .Context(), prepareWith);
            double doubleCompareTo = compareTo;

            Assert.AreEqual(expected, preparedComparison.CompareTo(doubleCompareTo));
        }
Exemple #9
0
        public virtual void Add(Transaction trans, object key)
        {
            KeyCantBeNull(key);
            IPreparedComparison preparedComparison = _keyHandler.PrepareComparison(trans.Context
                                                                                       (), key);

            Add(trans, preparedComparison, key);
        }
        public virtual void TestPrepareComparison()
        {
            StringBufferHandler handler            = new StringBufferHandler();
            IPreparedComparison preparedComparison = handler.PrepareComparison(Trans().Context
                                                                                   (), _bufferValue);

            Assert.IsGreater(preparedComparison.CompareTo("43"), 0);
        }
Exemple #11
0
 private bool CompareEquals(IPreparedComparison preparedComparison, Transaction trans
                            , ByteArrayBuffer reader, int index)
 {
     if (CanWrite())
     {
         return(CompareInWriteMode(preparedComparison, index) == 0);
     }
     return(CompareInReadMode(trans, preparedComparison, reader, index) == 0);
 }
Exemple #12
0
        public virtual BTreeNodeSearchResult SearchLeaf(Transaction trans, IPreparedComparison
                                                        preparedComparison, SearchTarget target)
        {
            EnsureActive(trans);
            BTreeNodeSearchResult result = _root.SearchLeaf(trans, preparedComparison, target
                                                            );

            ConvertCacheEvictedNodesToReadMode();
            return(result);
        }
Exemple #13
0
 internal virtual void PrepareComparison(QField a_field)
 {
     if (IsNullConstraint() & !a_field.IsArray())
     {
         _preparedComparison = Null.Instance;
     }
     else
     {
         _preparedComparison = a_field.PrepareComparison(Context(), i_object);
     }
 }
        public virtual IPreparedComparison PrepareComparison(IContext context, object fieldIndexKey
                                                             )
        {
            IFieldIndexKey      source = (IFieldIndexKey)fieldIndexKey;
            IPreparedComparison preparedValueComparison = _valueHandler.PrepareComparison(context
                                                                                          , source.Value());
            IPreparedComparison preparedParentIdComparison = _parentIdHandler.NewPrepareCompare
                                                                 (source.ParentID());

            return(new _IPreparedComparison_67(preparedValueComparison, preparedParentIdComparison
                                               ));
        }
Exemple #15
0
        /// <returns>
        /// the split node if this node is split
        /// or this if the first key has changed
        /// </returns>
        public Db4objects.Db4o.Internal.Btree.BTreeNode Add(Transaction trans, IPreparedComparison
                                                            preparedComparison, object obj)
        {
            ByteArrayBuffer reader = PrepareRead(trans);
            Searcher        s      = Search(trans, preparedComparison, reader);

            if (_isLeaf)
            {
                PrepareWrite(trans);
                SetStateDirty();
                if (WasRemoved(trans, s))
                {
                    CancelRemoval(trans, obj, s.Cursor());
                    return(null);
                }
                if (s.Count() > 0 && !s.BeforeFirst())
                {
                    s.MoveForward();
                }
                PrepareInsert(s.Cursor());
                _keys[s.Cursor()] = ApplyNewAddPatch(trans, obj);
            }
            else
            {
                Db4objects.Db4o.Internal.Btree.BTreeNode childNode        = Child(reader, s.Cursor());
                Db4objects.Db4o.Internal.Btree.BTreeNode childNodeOrSplit = childNode.Add(trans,
                                                                                          preparedComparison, obj);
                if (childNodeOrSplit == null)
                {
                    return(null);
                }
                PrepareWrite(trans);
                SetStateDirty();
                _keys[s.Cursor()] = childNode._keys[0];
                if (childNode != childNodeOrSplit)
                {
                    int splitCursor = s.Cursor() + 1;
                    PrepareInsert(splitCursor);
                    _keys[splitCursor]     = childNodeOrSplit._keys[0];
                    _children[splitCursor] = childNodeOrSplit;
                }
            }
            if (MustSplit())
            {
                return(Split(trans));
            }
            if (s.Cursor() == 0)
            {
                return(this);
            }
            return(null);
        }
Exemple #16
0
        internal virtual bool Evaluate(QConObject constraint, QCandidate candidate, object
                                       obj)
        {
            IPreparedComparison prepareComparison = constraint.PrepareComparison(candidate);

            if (obj == null)
            {
                return(prepareComparison is Null);
            }
            if (prepareComparison is PreparedArrayContainsComparison)
            {
                return(((PreparedArrayContainsComparison)prepareComparison).IsEqual(obj));
            }
            return(prepareComparison.CompareTo(obj) == 0);
        }
Exemple #17
0
        internal override bool Evaluate(QConObject constraint, QCandidate candidate, object
                                        obj)
        {
            if (obj == null)
            {
                return(false);
            }
            IPreparedComparison preparedComparison = constraint.PrepareComparison(candidate);

            if (preparedComparison is PreparedArrayContainsComparison)
            {
                return(((PreparedArrayContainsComparison)preparedComparison).IsGreaterThan(obj));
            }
            return(preparedComparison.CompareTo(obj) > 0);
        }
Exemple #18
0
        public virtual IPreparedComparison PrepareComparison(IContext context, object fieldIndexKey
                                                             )
        {
            if (fieldIndexKey == null)
            {
                fieldIndexKey = new FieldIndexKeyImpl(int.MaxValue, null);
            }
            IFieldIndexKey      source = (IFieldIndexKey)fieldIndexKey;
            IPreparedComparison preparedValueComparison = _valueHandler.PrepareComparison(context
                                                                                          , source.Value());
            IPreparedComparison preparedParentIdComparison = _parentIdHandler.NewPrepareCompare
                                                                 (source.ParentID());

            return(new _IPreparedComparison_65(preparedValueComparison, preparedParentIdComparison
                                               ));
        }
Exemple #19
0
        public virtual void Add(Transaction trans, IPreparedComparison preparedComparison
                                , object key)
        {
            EnsureActive(trans);
            Enlist(trans);
            BTreeNode rootOrSplit = _root.Add(trans, preparedComparison, key);

            if (rootOrSplit != null && rootOrSplit != _root)
            {
                EnsureDirty(trans);
                _root = new BTreeNode(trans, _root, rootOrSplit);
                _root.Write(trans.SystemTransaction());
                AddNode(_root);
            }
            ConvertCacheEvictedNodesToReadMode();
        }
Exemple #20
0
        private IBTreeRange SearchRange(Transaction trans, IPreparedComparison preparedComparison
                                        )
        {
            EnsureActive(trans);
            // TODO: Optimize the following.
            //       Part of the search operates against the same nodes.
            //       As long as the bounds are on one node, the search
            //       should walk the nodes in one go.
            BTreeNodeSearchResult start = SearchLeaf(trans, preparedComparison, SearchTarget.
                                                     Lowest);
            BTreeNodeSearchResult end = SearchLeaf(trans, preparedComparison, SearchTarget.Highest
                                                   );
            IBTreeRange range = start.CreateIncludingRange(end);

            ConvertCacheEvictedNodesToReadMode();
            return(range);
        }
        private void AssertHandlerComparison(IComparable4 handler, object smaller, object
                                             greater)
        {
            IPreparedComparison comparable = handler.PrepareComparison(Context(), smaller);

            Assert.IsNotNull(comparable);
            Assert.AreEqual(0, comparable.CompareTo(smaller));
            Assert.IsSmaller(0, comparable.CompareTo(greater));
            comparable = handler.PrepareComparison(Context(), greater);
            Assert.IsNotNull(comparable);
            Assert.AreEqual(0, comparable.CompareTo(greater));
            Assert.IsGreater(0, comparable.CompareTo(smaller));
            comparable = handler.PrepareComparison(Context(), null);
            Assert.IsNotNull(comparable);
            Assert.AreEqual(0, comparable.CompareTo(null));
            Assert.IsSmaller(0, comparable.CompareTo(smaller));
        }
Exemple #22
0
        public virtual object Remove(Transaction trans, object key)
        {
            BTreePointer bTreePointer = SearchPointer(trans, key);

            if (bTreePointer == null)
            {
                return(null);
            }
            object result = bTreePointer.Key();

            Enlist(trans);
            IPreparedComparison preparedComparison = KeyHandler().PrepareComparison(trans.Context
                                                                                        (), key);
            BTreeNode node = bTreePointer.Node();

            node.Remove(trans, preparedComparison, key, bTreePointer.Index());
            ConvertCacheEvictedNodesToReadMode();
            return(result);
        }
Exemple #23
0
        private Searcher Search(Transaction trans, IPreparedComparison preparedComparison
                                , ByteArrayBuffer reader, SearchTarget target)
        {
            Searcher s = new Searcher(target, _count);

            if (CanWrite())
            {
                while (s.Incomplete())
                {
                    s.ResultIs(CompareInWriteMode(preparedComparison, s.Cursor()));
                }
            }
            else
            {
                while (s.Incomplete())
                {
                    s.ResultIs(CompareInReadMode(trans, preparedComparison, reader, s.Cursor()));
                }
            }
            return(s);
        }
Exemple #24
0
        private BTreeNodeSearchResult FindLowestLeafMatch(Transaction trans, IPreparedComparison
                                                          preparedComparison, ByteArrayBuffer reader, int index)
        {
            if (index >= 0)
            {
                if (!CompareEquals(preparedComparison, trans, reader, index))
                {
                    return(null);
                }
                if (index > 0)
                {
                    var res = FindLowestLeafMatch(trans, preparedComparison, reader
                                                  , index - 1);
                    if (res != null)
                    {
                        return(res);
                    }
                    return(CreateMatchingSearchResult(trans, reader, index));
                }
            }
            var node = PreviousNode();

            if (node != null)
            {
                var nodeReader = node.PrepareRead(trans);
                var res        = node.FindLowestLeafMatch(trans, preparedComparison, nodeReader
                                                          , node.LastIndex());
                if (res != null)
                {
                    return(res);
                }
            }
            if (index < 0)
            {
                return(null);
            }
            return(CreateMatchingSearchResult(trans, reader, index));
        }
Exemple #25
0
 internal override void EvaluateSelf()
 {
     if (DTrace.enabled)
     {
         DTrace.EvaluateSelf.Log(Id());
     }
     if (_classMetadata != null)
     {
         if (!(_classMetadata is PrimitiveTypeMetadata))
         {
             if (!i_evaluator.Identity() && (_classMetadata.TypeHandler() is StandardReferenceTypeHandler
                                             ))
             {
                 _checkClassMetadataOnly = true;
             }
             object transactionalObject = _classMetadata.WrapWithTransactionContext(Transaction
                                                                                        (), i_object);
             _preparedComparison = _classMetadata.PrepareComparison(Context(), transactionalObject
                                                                    );
         }
     }
     base.EvaluateSelf();
     _checkClassMetadataOnly = false;
 }
Exemple #26
0
        public virtual BTreePointer SearchPointer(Transaction trans, object key)
        {
            EnsureActive(trans);
            KeyCantBeNull(key);
            IPreparedComparison preparedComparison = KeyHandler().PrepareComparison(trans.Context
                                                                                        (), key);
            BTreeNodeSearchResult start = SearchLeaf(trans, preparedComparison, SearchTarget.
                                                     Lowest);
            BTreePointer bTreePointer = start.FirstValidPointer();

            if (bTreePointer == null)
            {
                ConvertCacheEvictedNodesToReadMode();
                return(null);
            }
            object found = bTreePointer.Key();

            ConvertCacheEvictedNodesToReadMode();
            if (preparedComparison.CompareTo(found) == 0)
            {
                return(bTreePointer);
            }
            return(null);
        }
Exemple #27
0
		public void Remove(Transaction trans, IPreparedComparison preparedComparison, object
			 obj, int index)
		{
			if (Remove(trans, obj, index))
			{
				return;
			}
			// now we try if removal is OK for the next element in this node
			if (index != LastIndex())
			{
				if (CompareInWriteMode(preparedComparison, index + 1) != 0)
				{
					return;
				}
				Remove(trans, preparedComparison, obj, index + 1);
				return;
			}
			// nothing else worked so far, move on to the next node, try there
			Db4objects.Db4o.Internal.Btree.BTreeNode node = NextNode();
			if (node == null)
			{
				return;
			}
			node.PrepareWrite(trans);
			if (node.CompareInWriteMode(preparedComparison, 0) != 0)
			{
				return;
			}
			node.Remove(trans, preparedComparison, obj, 0);
		}
Exemple #28
0
		internal BTreeNodeSearchResult SearchLeaf(Transaction trans, IPreparedComparison 
			preparedComparison, SearchTarget target)
		{
			ByteArrayBuffer reader = PrepareRead(trans);
			Searcher s = Search(trans, preparedComparison, reader, target);
			if (!_isLeaf)
			{
				return Child(reader, s.Cursor()).SearchLeaf(trans, preparedComparison, target);
			}
			if (!s.FoundMatch() || target == SearchTarget.Any || target == SearchTarget.Highest)
			{
				return new BTreeNodeSearchResult(trans, reader, Btree(), s, this);
			}
			if (target == SearchTarget.Lowest)
			{
				BTreeNodeSearchResult res = FindLowestLeafMatch(trans, preparedComparison, s.Cursor
					() - 1);
				if (res != null)
				{
					return res;
				}
				return CreateMatchingSearchResult(trans, reader, s.Cursor());
			}
			throw new InvalidOperationException();
		}
Exemple #29
0
		private BTreeNodeSearchResult FindLowestLeafMatch(Transaction trans, IPreparedComparison
			 preparedComparison, int index)
		{
			return FindLowestLeafMatch(trans, preparedComparison, PrepareRead(trans), index);
		}
Exemple #30
0
 private Searcher Search(Transaction trans, IPreparedComparison preparedComparison
                         , ByteArrayBuffer reader)
 {
     return(Search(trans, preparedComparison, reader, SearchTarget.Any));
 }
			public _IPreparedComparison_67(IPreparedComparison preparedValueComparison, IPreparedComparison
				 preparedParentIdComparison)
			{
				this.preparedValueComparison = preparedValueComparison;
				this.preparedParentIdComparison = preparedParentIdComparison;
			}
Exemple #32
0
		private int CompareInReadMode(Transaction trans, IPreparedComparison preparedComparison
			, ByteArrayBuffer reader, int index)
		{
			SeekKey(reader, index);
			return -preparedComparison.CompareTo(KeyHandler().ReadIndexEntry(trans.Context(), 
				reader));
		}
Exemple #33
0
		internal override void EvaluateSelf()
		{
			if (DTrace.enabled)
			{
				DTrace.EvaluateSelf.Log(Id());
			}
			if (_classMetadata != null)
			{
				if (!(_classMetadata is PrimitiveTypeMetadata))
				{
					if (!i_evaluator.Identity() && (_classMetadata.TypeHandler() is StandardReferenceTypeHandler
						))
					{
						_checkClassMetadataOnly = true;
					}
					object transactionalObject = _classMetadata.WrapWithTransactionContext(Transaction
						(), i_object);
					_preparedComparison = _classMetadata.PrepareComparison(Context(), transactionalObject
						);
				}
			}
			base.EvaluateSelf();
			_checkClassMetadataOnly = false;
		}
Exemple #34
0
		internal override void Unmarshall(Transaction trans)
		{
			if (i_trans != null)
			{
				return;
			}
			base.Unmarshall(trans);
			if (i_object == null)
			{
				_preparedComparison = Null.Instance;
			}
			if (i_classMetadataID != 0)
			{
				_classMetadata = trans.Container().ClassMetadataForID(i_classMetadataID);
			}
			if (i_field != null)
			{
				i_field.Unmarshall(trans);
			}
			if (i_objectID > 0)
			{
				object obj = trans.Container().TryGetByID(trans, i_objectID);
				if (obj != null)
				{
					i_object = obj;
				}
			}
		}
Exemple #35
0
		private int CompareInWriteMode(IPreparedComparison preparedComparison, int index)
		{
			return -preparedComparison.CompareTo(Key(index));
		}
Exemple #36
0
 private int CompareInWriteMode(IPreparedComparison preparedComparison, int index)
 {
     return(-preparedComparison.CompareTo(Key(index)));
 }
Exemple #37
0
		public virtual BTreeNodeSearchResult SearchLeaf(Transaction trans, IPreparedComparison
			 preparedComparison, SearchTarget target)
		{
			EnsureActive(trans);
			BTreeNodeSearchResult result = _root.SearchLeaf(trans, preparedComparison, target
				);
			ConvertCacheEvictedNodesToReadMode();
			return result;
		}
Exemple #38
0
		private IBTreeRange SearchRange(Transaction trans, IPreparedComparison preparedComparison
			)
		{
			EnsureActive(trans);
			// TODO: Optimize the following.
			//       Part of the search operates against the same nodes.
			//       As long as the bounds are on one node, the search
			//       should walk the nodes in one go.
			BTreeNodeSearchResult start = SearchLeaf(trans, preparedComparison, SearchTarget.
				Lowest);
			BTreeNodeSearchResult end = SearchLeaf(trans, preparedComparison, SearchTarget.Highest
				);
			IBTreeRange range = start.CreateIncludingRange(end);
			ConvertCacheEvictedNodesToReadMode();
			return range;
		}
Exemple #39
0
		public virtual void Add(Transaction trans, IPreparedComparison preparedComparison
			, object key)
		{
			EnsureActive(trans);
			Enlist(trans);
			BTreeNode rootOrSplit = _root.Add(trans, preparedComparison, key);
			if (rootOrSplit != null && rootOrSplit != _root)
			{
				EnsureDirty(trans);
				_root = new BTreeNode(trans, _root, rootOrSplit);
				_root.Write(trans.SystemTransaction());
				AddNode(_root);
			}
			ConvertCacheEvictedNodesToReadMode();
		}
Exemple #40
0
 private BTreeNodeSearchResult FindLowestLeafMatch(Transaction trans, IPreparedComparison
                                                   preparedComparison, int index)
 {
     return(FindLowestLeafMatch(trans, preparedComparison, PrepareRead(trans), index));
 }
Exemple #41
0
		private Searcher Search(Transaction trans, IPreparedComparison preparedComparison
			, ByteArrayBuffer reader)
		{
			return Search(trans, preparedComparison, reader, SearchTarget.Any);
		}
Exemple #42
0
		private bool CompareEquals(IPreparedComparison preparedComparison, Transaction trans
			, ByteArrayBuffer reader, int index)
		{
			if (CanWrite())
			{
				return CompareInWriteMode(preparedComparison, index) == 0;
			}
			return CompareInReadMode(trans, preparedComparison, reader, index) == 0;
		}
Exemple #43
0
		internal virtual void PrepareComparison(QField a_field)
		{
			if (IsNullConstraint() & !a_field.IsArray())
			{
				_preparedComparison = Null.Instance;
			}
			else
			{
				_preparedComparison = a_field.PrepareComparison(Context(), i_object);
			}
		}
Exemple #44
0
 public _IPreparedComparison_65(IPreparedComparison preparedValueComparison, IPreparedComparison
                                preparedParentIdComparison)
 {
     this.preparedValueComparison    = preparedValueComparison;
     this.preparedParentIdComparison = preparedParentIdComparison;
 }
Exemple #45
0
		private BTreeNodeSearchResult FindLowestLeafMatch(Transaction trans, IPreparedComparison
			 preparedComparison, ByteArrayBuffer reader, int index)
		{
			if (index >= 0)
			{
				if (!CompareEquals(preparedComparison, trans, reader, index))
				{
					return null;
				}
				if (index > 0)
				{
					BTreeNodeSearchResult res = FindLowestLeafMatch(trans, preparedComparison, reader
						, index - 1);
					if (res != null)
					{
						return res;
					}
					return CreateMatchingSearchResult(trans, reader, index);
				}
			}
			Db4objects.Db4o.Internal.Btree.BTreeNode node = PreviousNode();
			if (node != null)
			{
				ByteArrayBuffer nodeReader = node.PrepareRead(trans);
				BTreeNodeSearchResult res = node.FindLowestLeafMatch(trans, preparedComparison, nodeReader
					, node.LastIndex());
				if (res != null)
				{
					return res;
				}
			}
			if (index < 0)
			{
				return null;
			}
			return CreateMatchingSearchResult(trans, reader, index);
		}
Exemple #46
0
		private Searcher Search(Transaction trans, IPreparedComparison preparedComparison
			, ByteArrayBuffer reader, SearchTarget target)
		{
			Searcher s = new Searcher(target, _count);
			if (CanWrite())
			{
				while (s.Incomplete())
				{
					s.ResultIs(CompareInWriteMode(preparedComparison, s.Cursor()));
				}
			}
			else
			{
				while (s.Incomplete())
				{
					s.ResultIs(CompareInReadMode(trans, preparedComparison, reader, s.Cursor()));
				}
			}
			return s;
		}
Exemple #47
0
		/// <returns>
		/// the split node if this node is split
		/// or this if the first key has changed
		/// </returns>
		public Db4objects.Db4o.Internal.Btree.BTreeNode Add(Transaction trans, IPreparedComparison
			 preparedComparison, object obj)
		{
			ByteArrayBuffer reader = PrepareRead(trans);
			Searcher s = Search(trans, preparedComparison, reader);
			if (_isLeaf)
			{
				PrepareWrite(trans);
				SetStateDirty();
				if (WasRemoved(trans, s))
				{
					CancelRemoval(trans, obj, s.Cursor());
					return null;
				}
				if (s.Count() > 0 && !s.BeforeFirst())
				{
					s.MoveForward();
				}
				PrepareInsert(s.Cursor());
				_keys[s.Cursor()] = ApplyNewAddPatch(trans, obj);
			}
			else
			{
				Db4objects.Db4o.Internal.Btree.BTreeNode childNode = Child(reader, s.Cursor());
				Db4objects.Db4o.Internal.Btree.BTreeNode childNodeOrSplit = childNode.Add(trans, 
					preparedComparison, obj);
				if (childNodeOrSplit == null)
				{
					return null;
				}
				PrepareWrite(trans);
				SetStateDirty();
				_keys[s.Cursor()] = childNode._keys[0];
				if (childNode != childNodeOrSplit)
				{
					int splitCursor = s.Cursor() + 1;
					PrepareInsert(splitCursor);
					_keys[splitCursor] = childNodeOrSplit._keys[0];
					_children[splitCursor] = childNodeOrSplit;
				}
			}
			if (MustSplit())
			{
				return Split(trans);
			}
			if (s.Cursor() == 0)
			{
				return this;
			}
			return null;
		}