Esempio n. 1
0
        /// <summary>
        /// Find witch index will be used and run Execute method
        /// </summary>
        public virtual IEnumerable <IndexNode> Run(CollectionPage col, IndexService indexer)
        {
            // get index for this query
            var index = col.GetCollectionIndex(this.Name);

            if (index == null)
            {
                throw LiteException.IndexNotFound(this.Name);
            }

            // execute query to get all IndexNodes
            return(this.Execute(indexer, index));
        }
Esempio n. 2
0
        /// <summary>
        /// Find witch index will be used and run Execute method
        /// </summary>
        public virtual async IAsyncEnumerable <IndexNode> Run(CollectionPage col, IndexService indexer)
        {
            // get index for this query
            var index = col.GetCollectionIndex(this.Name);

            if (index == null)
            {
                throw LiteException.IndexNotFound(this.Name);
            }

            var distinct = new HashSet <PageAddress>();

            await foreach (var node in this.Execute(indexer, index))
            {
                // distinct by dataBlock
                if (distinct.Contains(node.DataBlock) == false)
                {
                    distinct.Add(node.DataBlock);

                    yield return(node);
                }
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Implement internal update document
        /// </summary>
        private bool UpdateDocument(Snapshot snapshot, CollectionPage col, BsonDocument doc, IndexService indexer, DataService data)
        {
            // normalize id before find
            var id = doc["_id"];

            // validate id for null, min/max values
            if (id.IsNull || id.IsMinValue || id.IsMaxValue)
            {
                throw LiteException.InvalidDataType("_id", id);
            }

            // find indexNode from pk index
            var pkNode = indexer.Find(col.PK, id, false, LiteDB.Query.Ascending);

            // if not found document, no updates
            if (pkNode == null)
            {
                return(false);
            }

            // update data storage
            data.Update(col, pkNode.DataBlock, doc);

            // get all current non-pk index nodes from this data block (slot, key, nodePosition)
            var oldKeys = indexer.GetNodeList(pkNode.NextNode)
                          .Select(x => new Tuple <byte, BsonValue, PageAddress>(x.Slot, x.Key, x.Position))
                          .ToArray();

            // build a list of all new key index keys
            var newKeys = new List <Tuple <byte, BsonValue, string> >();

            foreach (var index in col.GetCollectionIndexes().Where(x => x.Name != "_id"))
            {
                // getting all keys from expression over document
                var keys = index.BsonExpr.Execute(doc, _header.Pragmas.Collation);

                foreach (var key in keys)
                {
                    newKeys.Add(new Tuple <byte, BsonValue, string>(index.Slot, key, index.Name));
                }
            }

            if (oldKeys.Length == 0 && newKeys.Count == 0)
            {
                return(true);
            }

            // get a list of all nodes that are in oldKeys but not in newKeys (must delete)
            var toDelete = new HashSet <PageAddress>(oldKeys
                                                     .Where(x => newKeys.Any(n => n.Item1 == x.Item1 && n.Item2 == x.Item2) == false)
                                                     .Select(x => x.Item3));

            // get a list of all keys that are not in oldKeys (must insert)
            var toInsert = newKeys
                           .Where(x => oldKeys.Any(o => o.Item1 == x.Item1 && o.Item2 == x.Item2) == false)
                           .ToArray();

            // if nothing to change, just exit
            if (toDelete.Count == 0 && toInsert.Length == 0)
            {
                return(true);
            }

            // delete nodes and return last keeped node in list
            var last = indexer.DeleteList(pkNode.Position, toDelete);

            // now, insert all new nodes
            foreach (var elem in toInsert)
            {
                var index = col.GetCollectionIndex(elem.Item3);

                last = indexer.AddNode(index, elem.Item2, pkNode.DataBlock, last);
            }

            return(true);
        }