public void Loop_Test() { using (var tmp = new TempFile()) { using (var db = new LiteEngine(tmp.Filename)) { db.Insert("col", new BsonDocument { { "Number", 1 } }); db.Insert("col", new BsonDocument { { "Number", 2 } }); db.Insert("col", new BsonDocument { { "Number", 3 } }); db.Insert("col", new BsonDocument { { "Number", 4 } }); } using (var db = new LiteEngine(tmp.Filename)) { foreach (var doc in db.Find("col", Query.All())) { doc["Name"] = "John"; db.Update("col", doc); } db.EnsureIndex("col", "Name"); var all = db.Find("col", Query.EQ("Name", "John")); Assert.AreEqual(4, all.Count()); } } }
public void Index_Order() { using (var tmp = new TempFile()) using (var db = new LiteEngine(tmp.Filename)) { db.Insert("col", new BsonDocument { { "text", "D" } }); db.Insert("col", new BsonDocument { { "text", "A" } }); db.Insert("col", new BsonDocument { { "text", "E" } }); db.Insert("col", new BsonDocument { { "text", "C" } }); db.Insert("col", new BsonDocument { { "text", "B" } }); db.EnsureIndex("col", "text"); var asc = string.Join("", db.Find("col", Query.All("text")) .Select(x => x["text"].AsString) .ToArray()); var desc = string.Join("", db.Find("col", Query.All("text", Query.Descending)) .Select(x => x["text"].AsString) .ToArray()); Assert.AreEqual("ABCDE", asc); Assert.AreEqual("EDCBA", desc); var indexes = db.GetIndexes("col"); Assert.AreEqual(1, indexes.Count(x => x.Field == "text")); } }
public void Thread_Transaction_Test() { using (var file = new TempFile()) using (var db = new LiteEngine(file.Filename)) { // insert first document db.Insert("col", new BsonDocument { { "_id", 1 }, { "count", 1 } }); // use parallel Parallel.For(1, 10000, (i) => { lock (db) { var doc = db.Find("col", Query.EQ("_id", 1)).Single(); doc["count"] = doc["count"].AsInt32 + 1; db.Update("col", doc); } }); Assert.AreEqual(10000, db.Find("col", Query.EQ("_id", 1)).Single()["count"].AsInt32); } }
public void Engine_Upsert_Test() { using (var file = new TempFile()) using (var db = new LiteEngine(file.Filename)) { var doc1 = new BsonDocument { { "_id", 1 }, { "name", "John" } }; var u1 = db.Upsert("col", doc1); // true (insert) doc1["name"] = "changed"; var u2 = db.Upsert("col", doc1); // false (update) Assert.AreEqual(true, u1); Assert.AreEqual(false, u2); // get data from db var r = db.Find("col", Query.EQ("_id", 1)).Single(); // test changed value Assert.AreEqual(doc1["name"].AsString, r["name"].AsString); } }
public void Crypto_Datafile() { var data = new MemoryStream(); var log = new MemoryStream(); var settings = new EngineSettings { DataStream = data, LogStream = log, Password = "******" }; using (var e = new LiteEngine(settings)) { this.CreateDatabase(e); // find string inside stream var dataStr = Encoding.UTF8.GetString(data.ToArray()); // encrypted datafile will not found plain strings Assert.IsFalse(dataStr.Contains("mycol")); Assert.IsFalse(dataStr.Contains("Mauricio")); // but document exists! var doc = e.Find("mycol", "_id=1").First(); Assert.AreEqual("Mauricio", doc["name"].AsString); // encrypted datafile will consume 5 pages: 1 salt page, 1 header, 1 collection, 1 data e 1 index Assert.AreEqual(5, data.Length / 8192); } }
public void MultiKey_InsertUpdate_Test() { using (var file = new TempFile()) using (var db = new LiteEngine(file.Filename)) { db.Insert("col", GetDocs(1, 1, 1, 2, 3)); db.Insert("col", GetDocs(2, 2, 2, 2, 4)); db.Insert("col", GetDocs(3, 3, 3)); // create index afer documents are in collection db.EnsureIndex("col", "list"); db.EnsureIndex("col", "rnd"); db.Update("col", GetDocs(2, 2, 9, 9)); // try find var r = string.Join(",", db.Find("col", Query.EQ("list", 2)).Select(x => x["_id"].ToString())); Assert.AreEqual("1", r); Assert.AreEqual(3, db.Count("col", null)); Assert.AreEqual(3, db.Count("col", Query.All())); // 5 keys = [1, 2, 3],[3],[9] var l = string.Join(",", db.FindIndex("col", Query.All("list"))); Assert.AreEqual("1,2,3,3,9", l); // count should be count only documents - not index nodes Assert.AreEqual(3, db.Count("col", Query.All("list"))); } }
private IEnumerable <BsonDocument> FetchDocuments(LiteEngine engine, string col, Query query, List <UpdateData> updates) { // query document accord query and return modified only documents foreach (var doc in engine.Find(col, query)) { var docChanged = false; foreach (var update in updates) { var itemChanged = false; if (update.Value == null) { itemChanged = doc.Set(update.Path, update.Expr, update.Add); } else { itemChanged = doc.Set(update.Path, update.Value, update.Add); } if (itemChanged) { docChanged = true; } } // execute update only if document was changed if (docChanged) { yield return(doc); } } }
public void Query() { for (var i = 0; i < _count; i++) { _db.Find("col", LiteDB.Query.EQ("_id", i)).Single(); } }
/// <summary> /// Read all colleciton, indexes and documents inside current datafile /// Drop per index, per collection and shrink /// This steps will check/validate all file data /// </summary> private void CheckIntegrity() { using (var db = new LiteEngine(this.Filename)) { var cols = db.GetCollectionNames().ToArray(); foreach (var col in cols) { var indexes = db.GetIndexes(col).ToArray(); foreach (var idx in indexes) { var q = db.Find(col, Query.All(idx.Field)); foreach (var doc in q) { // document are ok! } // lets drop this index (if not _id) if (idx.Field != "_id") { db.DropIndex(col, idx.Field); } } // and drop collection db.DropCollection(col); } // and now shrink db.Shrink(); } }
public void Change_Thread_Culture() { using (var f = new TempFile()) { var current = CultureInfo.CurrentCulture; CultureInfo.CurrentCulture = new CultureInfo("fi"); // store in database using "fi" culture using (var e = new LiteEngine(f.Filename)) { e.Insert("col1", data.Select(x => new BsonDocument { ["_id"] = x }), BsonAutoId.Int32); } // change current culture do "en-GB" CultureInfo.CurrentCulture = new CultureInfo("en-gb"); using (var e = new LiteEngine(f.Filename)) { foreach (var id in data) { var doc = e.Find("col1", BsonExpression.Create("_id = @0", id)).Single(); doc["_id"].AsString.Should().Be(id); } } CultureInfo.CurrentCulture = current; } }
public void QueryFirst_Test() { using (var file = new TempFile()) using (var db = new LiteEngine(file.Filename)) { db.Insert("col", new BsonDocument[] { new BsonDocument { { "_id", 1 }, { "name", "e" } }, new BsonDocument { { "_id", 2 }, { "name", "d" } }, new BsonDocument { { "_id", 3 }, { "name", "c" } }, new BsonDocument { { "_id", 4 }, { "name", "b" } }, new BsonDocument { { "_id", 5 }, { "name", "a" } } }); var first = db.Find("col", Query.All()).First(); Assert.AreEqual("e", first["name"].AsString); } }
public void Engine_QueryUpdate_Test() { using (var file = new TempFile()) using (var db = new LiteEngine(file.Filename)) { db.EnsureIndex("col", "name"); // insert 4 documents db.Insert("col", new BsonDocument { { "_id", 1 } }); db.Insert("col", new BsonDocument { { "_id", 2 } }); db.Insert("col", new BsonDocument { { "_id", 3 } }); db.Insert("col", new BsonDocument { { "_id", 4 } }); // query all documents and update name foreach (var d in db.Find("col", Query.All())) { d["name"] = "john"; db.Update("col", d); } // this simple test if same thread open a read mode and then open write lock mode Assert.AreEqual(4, db.Count("col", Query.EQ("name", "john"))); } }
public void Execute(LiteEngine engine, StringScanner s, Display display, InputCommand input, Env env) { var col = this.ReadCollection(engine, s); var query = this.ReadQuery(s); var skipLimit = this.ReadSkipLimit(s); var docs = engine.Find(col, query, skipLimit.Key, skipLimit.Value); display.WriteResult(new BsonArray(docs)); }
public void MemoryStream_Test() { var mem = new MemoryStream(); using (var db = new LiteEngine(mem)) { db.Insert("col", new BsonDocument { { "_id", 1 } , { "name", "John" } }); db.Insert("col", new BsonDocument { { "_id", 2 }, { "name", "Doe" } }); } using (var db = new LiteEngine(mem)) { var john = db.Find("col", Query.EQ("_id", 1)).FirstOrDefault(); var doe = db.Find("col", Query.EQ("_id", 2)).FirstOrDefault(); Assert.AreEqual("John", john["name"].AsString); Assert.AreEqual("Doe", doe["name"].AsString); } }
public void Loop_With_Update() { using (var tmp = new TempFile()) { // initialize database with 4 using (var db = new LiteEngine(tmp.Filename)) { db.Insert("col", new BsonDocument { { "Number", 1 } }, BsonType.Int32); db.Insert("col", new BsonDocument { { "Number", 2 } }, BsonType.Int32); db.Insert("col", new BsonDocument { { "Number", 3 } }, BsonType.Int32); db.Insert("col", new BsonDocument { { "Number", 4 } }, BsonType.Int32); db.Insert("col", new BsonDocument { { "Number", 5 } }, BsonType.Int32); } using (var db = new LiteEngine(tmp.Filename)) { foreach (var doc in db.Find("col", Query.All(), 0, 1000)) { var id = doc["_id"]; doc["Name"] = "John"; // inside this update, locker must be in write db.Update("col", doc); } db.EnsureIndex("col", "Name"); var all = db.Find("col", Query.EQ("Name", "John")); Assert.AreEqual(5, all.Count()); } } }
public IEnumerable <BsonValue> Execute(StringScanner s, LiteEngine engine) { var col = this.ReadCollection(engine, s); // try read any kind of expression var expression = BsonExpression.ReadExpression(s, false, false); // if not found a valid one, try read only as path (will add $. before) if (expression == null) { expression = BsonExpression.ReadExpression(s, true, true); } var query = Query.All(); // support into new_collection var into = s.Scan(@"\s*into\s+([\w-]+)", 1); var autoId = BsonType.ObjectId; // checks for autoId if (into.Length > 0) { var sid = s.Scan(@"\s+_?id:(int32|int64|int|long|objectid|datetime|date|guid)", 1).Trim().ToLower(); autoId = sid == "int32" || sid == "int" ? BsonType.Int32 : sid == "int64" || sid == "long" ? BsonType.Int64 : sid == "date" || sid == "datetime" ? BsonType.DateTime : sid == "guid" ? BsonType.Guid : BsonType.ObjectId; } if (s.Scan(@"\s*where\s*").Length > 0) { query = this.ReadQuery(s, true); } var skipLimit = this.ReadSkipLimit(s); var includes = this.ReadIncludes(s); s.ThrowIfNotFinish(); var docs = engine.Find(col, query, includes, skipLimit.Key, skipLimit.Value); if (into.Length > 0) { // insert into results to other collection collection var count = engine.InsertBulk(into, this.Execute(docs, expression), autoId: autoId); // return inserted documents return(new BsonValue[] { count }); } else { return(this.Execute(docs, expression).Select(x => x as BsonValue)); } }
public void Storage_ReadWriteStream_Test() { var HELLO1 = "Hello World LiteDB 1 ".PadRight(300000, '-') + "\nEND"; var HELLO2 = "Hello World LiteDB 2 - END"; using (var file = new TempFile()) using (var db = new LiteEngine(file.Filename)) { var sto = new LiteStorage(db); // insert HELLO1 file content using (var stream = sto.OpenWrite("f1", "f1.txt")) { using (var sw = new StreamWriter(stream)) { sw.Write(HELLO1); } } // test if was updated Length in _files collection var doc = db.Find("_files", Query.EQ("_id", "f1")).Single(); Assert.AreEqual(HELLO1.Length, doc["length"].AsInt32); using (var stream = sto.OpenRead("f1")) { var sr = new StreamReader(stream); var hello = sr.ReadToEnd(); Assert.AreEqual(HELLO1, hello); } // updating to HELLO2 content same file id using (var stream = sto.OpenWrite("f1", "f1.txt")) { using (var sw = new StreamWriter(stream)) { sw.Write(HELLO2); } } using (var stream = sto.OpenRead("f1")) { var sr = new StreamReader(stream); var hello = sr.ReadToEnd(); Assert.AreEqual(HELLO2, hello); } // now delete all sto.Delete("f1"); Assert.IsFalse(sto.Exists("f1")); } }
public void Engine_Insert_Test() { using (var file = new TempFile()) { using (var db = new LiteEngine(file.Filename)) { db.Insert("col", new BsonDocument { { "_id", 1 } , { "name", "John" } }); db.Insert("col", new BsonDocument { { "_id", 2 }, { "name", "Doe" } }); } using (var db = new LiteEngine(file.Filename)) { var john = db.Find("col", Query.EQ("_id", 1)).FirstOrDefault(); var doe = db.Find("col", Query.EQ("_id", 2)).FirstOrDefault(); Assert.AreEqual("John", john["name"].AsString); Assert.AreEqual("Doe", doe["name"].AsString); } } }
public void Encrypted_Database() { using (var encrypt = new TempFile()) using (var plain = new TempFile()) { // create a database with no password - plain data using (var db = new LiteEngine(plain.Filename)) { db.Insert("col", new BsonDocument { { "name", "Mauricio David" } }); } // read datafile to find "Mauricio" string Assert.IsTrue(plain.ReadAsText().Contains("Mauricio David")); // create a database with password using (var db = new LiteEngine(encrypt.Filename, "abc123")) { db.Insert("col", new BsonDocument { { "name", "Mauricio David" } }); } // test if is possible find "Mauricio" string Assert.IsFalse(encrypt.ReadAsText().Contains("Mauricio David")); // try access using wrong password try { using (var db = new LiteEngine(encrypt.Filename, "abc1234")) { Assert.Fail(); // can't work } } catch (LiteException ex) { Assert.IsTrue(ex.ErrorCode == 123); // wrong password } // open encrypted db and read document using (var db = new LiteEngine(encrypt.Filename, "abc123")) { var doc = db.Find("col", Query.All()).First(); Assert.AreEqual("Mauricio David", doc["name"].AsString); // let's remove password to work CheckIntegrety db.Shrink(null, null); } } }
public void MemoryStream_Test() { var mem = new MemoryStream(); using (var db = new LiteEngine(mem)) { db.Insert("col", new BsonDocument { { "_id", 1 }, { "name", "John" } }); db.Insert("col", new BsonDocument { { "_id", 2 }, { "name", "Doe" } }); } using (var db = new LiteEngine(mem)) { var john = db.Find("col", Query.EQ("_id", 1)).FirstOrDefault(); var doe = db.Find("col", Query.EQ("_id", 2)).FirstOrDefault(); Assert.AreEqual("John", john["name"].AsString); Assert.AreEqual("Doe", doe["name"].AsString); } }
public void Engine_Insert_Test() { using (var file = new TempFile()) { using (var db = new LiteEngine(file.Filename)) { db.Insert("col", new BsonDocument { { "_id", 1 }, { "name", "John" } }); db.Insert("col", new BsonDocument { { "_id", 2 }, { "name", "Doe" } }); } using (var db = new LiteEngine(file.Filename)) { var john = db.Find("col", Query.EQ("_id", 1)).FirstOrDefault(); var doe = db.Find("col", Query.EQ("_id", 2)).FirstOrDefault(); Assert.AreEqual("John", john["name"].AsString); Assert.AreEqual("Doe", doe["name"].AsString); } } }
public IEnumerable <BsonValue> Execute(StringScanner s, LiteEngine engine) { var col = ReadCollection(engine, s); var query = ReadQuery(s, false); var skipLimit = ReadSkipLimit(s); var includes = ReadIncludes(s); s.ThrowIfNotFinish(); var docs = engine.Find(col, query, includes, skipLimit.Key, skipLimit.Value); foreach (var doc in docs) { yield return(doc); } }
public void Encrypted_Test() { using (var encrypt = new TempFile()) using (var plain = new TempFile()) { // create a database with no password - plain data using (var db = new LiteEngine(plain.Filename)) { db.Insert("col", new BsonDocument { { "name", "Mauricio David" } }); } // read datafile to find "Mauricio" string Assert.IsTrue(plain.ReadAsText().Contains("Mauricio David")); // create a database with password using (var db = new LiteEngine(encrypt.Filename, "abc123")) { db.Insert("col", new BsonDocument { { "name", "Mauricio David" } }); } // test if is possible find "Mauricio" string Assert.IsFalse(encrypt.ReadAsText().Contains("Mauricio David")); // try access using wrong password try { using (var db = new LiteEngine(encrypt.Filename, "abc1234")) { Assert.Fail(); // can't work } } catch (LiteException ex) { Assert.IsTrue(ex.ErrorCode == 123); // wrong password } // open encrypted db and read document using (var db = new LiteEngine(encrypt.Filename, "abc123")) { var doc = db.Find("col", Query.All()).First(); Assert.AreEqual("Mauricio David", doc["name"].AsString); } } }
// [TestMethod] public void BigFile_Test() { using (var file = new TempFile()) using (var db = new LiteEngine(file.Filename)) { // create more than 4gb file while (file.Size < 4L * 1024 * 1024 * 1024) { db.Insert("col", GetDocs(5000)); } // now lets read all docs foreach (var d in db.Find("col", Query.All())) { // just read to check if there is any exception } } }
/// <summary> /// Simple test: insert new document and then update this document. Finish quering first 100 documents /// </summary> static void RunTask(LiteEngine db) { for (var i = 0; i < 10; i++) { var doc = new BsonDocument() { ["name"] = "testing - " + Guid.NewGuid() }; db.Insert("collection", doc, BsonType.Int32); doc["name"] = "changed name - " + Guid.NewGuid(); db.Update("collection", doc); } db.Find("collection", Query.LTE("_id", 100)).ToArray(); }
public void Thread_InsertQuery_Test() { const int N = 3000; var running = true; using (var file = new TempFile()) using (var db = new LiteEngine(file.Filename)) { db.Insert("col", new BsonDocument()); // insert basic document var ta = Task.Factory.StartNew(() => { for (var i = 0; i < N; i++) { var doc = new BsonDocument { { "_id", i } }; db.Insert("col", doc); } running = false; }); // query while insert var tb = Task.Factory.StartNew(() => { while (running) { db.Find("col", Query.All()).ToList(); } }); Task.WaitAll(ta, tb); Assert.AreEqual(N + 1, db.Count("col", Query.All())); } }
public void Engine_QueryUpdate_Test() { using (var file = new TempFile()) using (var db = new LiteEngine(file.Filename)) { db.EnsureIndex("col", "name"); // insert 4 documents db.Insert("col", new BsonDocument { { "_id", 1 } }); db.Insert("col", new BsonDocument { { "_id", 2 } }); db.Insert("col", new BsonDocument { { "_id", 3 } }); db.Insert("col", new BsonDocument { { "_id", 4 } }); // query all documents and update name foreach(var d in db.Find("col", Query.All())) { d["name"] = "john"; db.Update("col", d); } // this simple test if same thread open a read mode and then open write lock mode Assert.AreEqual(4, db.Count("col", Query.EQ("name", "john"))); } }
public void Concurrency_InsertQuery_Test() { const int N = 3000; var running = true; using (var file = new TempFile()) using (var db = new LiteEngine(file.Filename)) { db.Insert("col", new BsonDocument()); // insert basic document var ta = Task.Factory.StartNew(() => { for (var i = 0; i < N; i++) { var doc = new BsonDocument { { "_id", i } }; db.Insert("col", doc); } running = false; }); // query while insert var tb = Task.Factory.StartNew(() => { while (running) { db.Find("col", Query.All()).ToList(); } }); Task.WaitAll(ta, tb); Assert.AreEqual(N + 1, db.Count("col", Query.All())); } }
public void ReadOnlyFirst_Test() { using (var file = new TempFile()) { // just create file using (var c = new LiteEngine(file.Filename)) { c.Insert("col", new BsonDocument { { "_id", 1 } }); } // here there is no open datafile // open as read-only using (var r = new LiteEngine(new FileDiskService(file.Filename, new FileOptions { ReadOnly = true }))) { // just query var d = r.Find("col", Query.EQ("_id", 1)).FirstOrDefault(); Assert.AreEqual(1, d["_id"].AsInt32); // open database in read/write mode Task.Factory.StartNew(() => { using (var rw = new LiteEngine(file.Filename)) { rw.Insert("col", new BsonDocument { { "_id", 2 } }); } }).Wait(); } } }
public void ReadOnly_Test() { using (var file = new TempFile()) { // open database with read/write using (var db = new LiteEngine(file.Filename)) { // here datafile are in Read/Write db.Insert("col", new BsonDocument { { "_id", 1 } }); } using (var r = new LiteEngine(new FileDiskService(file.Filename, new FileOptions { FileMode = FileMode.ReadOnly }))) { var doc = r.Find("col", Query.EQ("_id", 1)).FirstOrDefault(); Assert.AreEqual(1, doc["_id"].AsInt32); // do not support write operation try { r.Insert("doc", new BsonDocument { { "_id", 2 } }); Assert.Fail("Do not accept write operation in readonly database"); } catch (NotSupportedException) { } } } }
public void Concurrency_LockTransaction_Test() { using (var file = new TempFile()) using (var db = new LiteEngine(file.Filename)) { // insert first document db.Insert("col", new BsonDocument { { "_id", 1 }, { "count", 1 } }); // use parallel Parallel.For(1, 10000, (i) => { lock(db) { var doc = db.Find("col", Query.EQ("_id", 1)).Single(); doc["count"] = doc["count"].AsInt32 + 1; db.Update("col", doc); } }); Assert.AreEqual(10000, db.Find("col", Query.EQ("_id", 1)).Single()["count"].AsInt32); } }
public void ReadOnly_Test() { using (var file = new TempFile()) { // open database with read/write using (var db = new LiteEngine(file.Filename)) { // here datafile are in Read/Write db.Insert("col", new BsonDocument { { "_id", 1 } }); // open datafile as readonly mode Task.Factory.StartNew(() => { using (var r = new LiteEngine(new FileDiskService(file.Filename, new FileOptions { ReadOnly = true }))) { var doc = r.Find("col", Query.EQ("_id", 1)).FirstOrDefault(); Assert.AreEqual(1, doc["_id"].AsInt32); // do not support write operation try { r.Insert("doc", new BsonDocument { { "_id", 2 } }); Assert.Fail("Do not accept write operation in readonly database"); } catch (LiteException ex) { if (ex.ErrorCode != LiteException.READ_ONLY_DATABASE) { Assert.Fail("Wrong exception"); } } } }).Wait(); // try open second datafile in write mode (must throw exception) Task.Factory.StartNew(() => { try { // try open datafile as read/write using (var rw = new LiteEngine(new FileDiskService(file.Filename, new FileOptions { Timeout = TimeSpan.FromSeconds(3) }))) { Assert.Fail("Do not open this datafile"); } } catch (LiteException ex) { if (ex.ErrorCode != LiteException.LOCK_TIMEOUT) { Assert.Fail("Wrong exception"); } } }).Wait(); } } }
/// <summary> /// Count result but reading all documents from database /// </summary> public long Count() => _engine.Find("col", _query).Count();
public static BsonDocument GetPageLog(this LiteEngine engine, int pageID) { return(engine.Find("$dump_log", "pageID = " + pageID).Last()); }
public void ExecuteQuery(bool createIndex) { using (var db = new LiteEngine(new MemoryStream())) { db.Insert("col", new BsonDocument[] { new BsonDocument { ["age"] = 1, ["name"] = "a" }, new BsonDocument { ["age"] = 2, ["name"] = "b" }, new BsonDocument { ["age"] = 3, ["name"] = "c" }, new BsonDocument { ["age"] = 4, ["name"] = "d" }, new BsonDocument { ["age"] = 5, ["name"] = "e" }, new BsonDocument { ["age"] = 6, ["name"] = "f" }, new BsonDocument { ["age"] = 7, ["name"] = "g" }, new BsonDocument { ["age"] = 8, ["name"] = "h" }, new BsonDocument { ["age"] = 9, ["name"] = "i" }, new BsonDocument { ["age"] = 9, ["name"] = "j" } }); if (createIndex) { db.EnsureIndex("col", "age"); db.EnsureIndex("col", "name"); } Func <Query, string> result = (q) => string.Join(",", db.Find("col", q).Select(x => x["name"].AsString)); Assert.AreEqual("a,b,c,d,e,f,g,h,i,j", result(Query.All())); Assert.AreEqual("a", result(Query.EQ("age", 1))); Assert.AreEqual("g", result(Query.EQ("age", 7))); Assert.AreEqual("h,i,j", result(Query.GT("age", 7))); Assert.AreEqual("g,h,i,j", result(Query.GTE("age", 7))); Assert.AreEqual("", result(Query.LT("age", 1))); Assert.AreEqual("a", result(Query.LTE("age", 1))); Assert.AreEqual("g,h,i,j", result(Query.Between("age", 7, 9))); Assert.AreEqual("a,b,c,d,e,f,g,h", result(Query.Not("age", 9))); Assert.AreEqual("a", result(Query.Not(Query.GTE("age", 2)))); Assert.AreEqual("a,g,i,j", result(Query.In("age", 1, 7, 9))); Assert.AreEqual("a", result(Query.StartsWith("name", "a"))); Assert.AreEqual("j", result(Query.And(Query.EQ("age", 9), Query.EQ("name", "j")))); Assert.AreEqual("j", result(Query.And(Query.GTE("age", 1), Query.And(Query.LTE("age", 9), Query.EQ("name", "j"))))); Assert.AreEqual("j", result(Query.And(Query.GTE("age", 1), Query.LTE("age", 9), Query.EQ("name", "j")))); Assert.AreEqual("a,i,j", result(Query.Or(Query.EQ("age", 1), Query.EQ("age", 9)))); Assert.AreEqual("b,d,f,h", result(Query.Where("age", (v) => v.AsInt32 % 2 == 0))); } }
public IEnumerable <BsonValue> Execute(StringScanner s, LiteEngine engine) { var col = this.ReadCollection(engine, s); var fields = new Dictionary <string, BsonExpression>(); var index = 0; // read all fields definitions (support AS as keyword no name field) while (!s.HasTerminated) { // try read any kind of expression var expression = BsonExpression.ReadExpression(s, false, false); // if not found a valid one, try read only as path (will add $. before) if (expression == null) { expression = BsonExpression.ReadExpression(s, true, true); } var key = s.Scan(@"\s*as\s+([\w-]+)", 1).TrimToNull() ?? this.NamedField(expression) ?? ("expr" + (++index)); // if key already exits, add with another name while (fields.ContainsKey(key)) { key = "expr" + (++index); } fields.Add(key, expression); if (s.Scan(@"\s*,\s*").Length > 0) { continue; } break; } // select command required output value, path or expression if (fields.Count == 0) { throw LiteException.SyntaxError(s, "Missing select path"); } var query = Query.All(); if (s.Scan(@"\s*where\s*").Length > 0) { query = this.ReadQuery(s, true); } var skipLimit = this.ReadSkipLimit(s); var includes = this.ReadIncludes(s); s.ThrowIfNotFinish(); var docs = engine.Find(col, query, includes, skipLimit.Key, skipLimit.Value); foreach (var doc in docs) { // if is a single value, return as just field if (fields.Count == 1) { foreach (var value in fields.Values.First().Execute(doc, false)) { yield return(value); } } else { var output = new BsonDocument(); foreach (var field in fields) { output[field.Key] = field.Value.Execute(doc, true).First(); } yield return(output); } } }