/// <summary> /// Implements insert documents in a collection - use a buffer to commit transaction in each buffer count /// </summary> public int Insert(string colName, IEnumerable <BsonDocument> docs) { return(this.Transaction <int>(colName, true, (col) => { var count = 0; foreach (var doc in docs) { BsonValue id; // if no _id, add one as ObjectId if (!doc.RawValue.TryGetValue("_id", out id)) { doc["_id"] = id = ObjectId.NewObjectId(); } // test if _id is a valid type if (id.IsNull || id.IsMinValue || id.IsMaxValue) { throw LiteException.InvalidDataType("_id", id); } _log.Write(Logger.COMMAND, "insert document on '{0}' :: _id = {1}", col.CollectionName, id); // serialize object var bytes = BsonSerializer.Serialize(doc); // storage in data pages - returns dataBlock address var dataBlock = _data.Insert(col, bytes); // store id in a PK index [0 array] var pk = _indexer.AddNode(col.PK, id); // do links between index <-> data block pk.DataBlock = dataBlock.Position; dataBlock.IndexRef[0] = pk.Position; // for each index, insert new IndexNode foreach (var index in col.GetIndexes(false)) { var key = doc.Get(index.Field); var node = _indexer.AddNode(index, key); // point my index to data object node.DataBlock = dataBlock.Position; // point my dataBlock dataBlock.IndexRef[index.Slot] = node.Position; } _cache.CheckPoint(); count++; } return count; })); }
/// <summary> /// Implement update command to a document inside a collection /// </summary> public int Update(string colName, IEnumerable <BsonDocument> docs) { return(this.Transaction <int>(colName, false, (col) => { // no collection, no updates if (col == null) { return 0; } var count = 0; foreach (var doc in docs) { // normalize id before find var id = doc["_id"].Normalize(col.PK.Options); // validate id for null, min/max values if (id.IsNull || id.IsMinValue || id.IsMaxValue) { throw LiteException.InvalidDataType("_id", id); } _log.Write(Logger.COMMAND, "update document on '{0}' :: _id = ", colName, id); // find indexNode from pk index var indexNode = _indexer.Find(col.PK, id, false, Query.Ascending); // if not found document, no updates if (indexNode == null) { continue; } // serialize document in bytes var bytes = BsonSerializer.Serialize(doc); // update data storage var dataBlock = _data.Update(col, indexNode.DataBlock, bytes); // delete/insert indexes - do not touch on PK foreach (var index in col.GetIndexes(false)) { var key = doc.Get(index.Field); var node = _indexer.GetNode(dataBlock.IndexRef[index.Slot]); // check if my index node was changed if (node.Key.CompareTo(key) != 0) { // remove old index node _indexer.Delete(index, node.Position); // and add a new one var newNode = _indexer.AddNode(index, key); // point my index to data object newNode.DataBlock = dataBlock.Position; // set my block page as dirty before change _pager.SetDirty(dataBlock.Page); // point my dataBlock dataBlock.IndexRef[index.Slot] = newNode.Position; } } _cache.CheckPoint(); count++; } return count; })); }