/// <summary> /// Read includes paths using comma delimiter: xxx include $.Books[*], $.Customer /// </summary> public string[] ReadIncludes(StringScanner s) { if (s.Scan(@"\s*include[s]?\s+").Length > 0) { var includes = new List <string>(); var include = BsonExpression.ReadExpression(s, true); if (include == null) { throw LiteException.SyntaxError(s, "Missing include paths"); } while (include != null && !s.HasTerminated) { includes.Add(include); // capture next only if found comma symbol include = s.Scan(@"\s*,\s*").Length > 0 ? BsonExpression.ReadExpression(s, true) : null; } return(includes.ToArray()); } return(new string[0]); }
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 IEnumerable <BsonValue> Execute(StringScanner s, LiteEngine engine) { var col = this.ReadCollection(engine, s); var value = JsonSerializer.Deserialize(s); var sid = s.Scan(@"\s+_?id:(int32|int64|int|long|objectid|datetime|date|guid)", 1).Trim().ToLower(); var 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; s.ThrowIfNotFinish(); if (value.IsArray) { var count = engine.InsertBulk(col, value.AsArray.RawValue.Select(x => x.AsDocument), autoId: autoId); yield return(count); } else if (value.IsDocument) { engine.Insert(col, new BsonDocument[] { value.AsDocument }, autoId); yield return(value.AsDocument["_id"]); } else { throw LiteException.SyntaxError(s, "Invalid JSON value (must be a document or an array)"); } }
public IEnumerable <BsonValue> Execute(StringScanner s, LiteEngine engine) { var col = this.ReadCollection(engine, s); var index = s.Scan(this.FieldPattern).Trim().ThrowIfEmpty("Missing field index name", s); s.ThrowIfNotFinish(); yield return(engine.DropIndex(col, index)); }
public IEnumerable <BsonValue> Execute(StringScanner s, LiteEngine engine) { var col = this.ReadCollection(engine, s); var newName = s.Scan(@"[\w-]+").ThrowIfEmpty("Invalid new collection name", s); s.ThrowIfNotFinish(); yield return(engine.RenameCollection(col, newName)); }
public IEnumerable <BsonValue> Execute(StringScanner s, LiteEngine engine) { var col = this.ReadCollection(engine, s); var index = s.Scan(this.FieldPattern).Trim(); if (!s.HasTerminated) { throw LiteException.SyntaxError(s, "Invalid field/index name"); } yield return(engine.Min(col, index.Length == 0 ? "_id" : index)); }
public IEnumerable <BsonValue> Execute(StringScanner s, LiteEngine engine) { var col = this.ReadCollection(engine, s); var filename = s.Scan(@".*"); using (var sr = new StreamReader(new FileStream(filename, System.IO.FileMode.Open))) { var docs = JsonSerializer.DeserializeArray(sr); yield return(engine.InsertBulk(col, docs.Select(x => x.AsDocument))); } }
/// <summary> /// Read includes paths using comma delimiter: xxx include $.Books[*], $.Customer /// </summary> public string[] ReadIncludes(StringScanner s) { if (s.Scan(@"\s*include[s]?\s+").Length > 0) { var includes = new List <string>(); var include = BsonExpression.ReadExpression(s, true, true); while (include != null) { includes.Add(include.Source); // capture next only if found comma symbol include = s.Scan(@"\s*,\s*").Length > 0 ? BsonExpression.ReadExpression(s, true, true) : null; } return(includes.ToArray()); } return(new string[0]); }
private Query ReadOneQuery(StringScanner s) { var field = BsonExpression.ReadExpression(s, false) ?? s.Scan(this.FieldPattern).Trim().ThrowIfEmpty("Invalid field", s); var oper = s.Scan(@"\s*(=|!=|>=|<=|>|<|like|starts[Ww]ith|in|between|contains)\s*").Trim().ToLower().ThrowIfEmpty("Invalid query operator", s); if (s.HasTerminated) { throw LiteException.SyntaxError(s, "Missing value"); } var value = JsonSerializer.Deserialize(s); switch (oper) { case "=": return(Query.EQ(field, value)); case "!=": return(Query.Not(field, value)); case ">": return(Query.GT(field, value)); case ">=": return(Query.GTE(field, value)); case "<": return(Query.LT(field, value)); case "<=": return(Query.LTE(field, value)); case "like": case "startswith": return(Query.StartsWith(field, value)); case "in": return(Query.In(field, value.AsArray)); case "between": return(Query.Between(field, value.AsArray[0], value.AsArray[1])); case "contains": return(Query.Contains(field, value)); default: throw new LiteException("Invalid query operator"); } }
public KeyValuePair <int, int> ReadSkipLimit(StringScanner s) { var skip = 0; var limit = int.MaxValue; if (s.Match(@"\s*skip\s+\d+")) { skip = Convert.ToInt32(s.Scan(@"\s*skip\s+(\d+)\s*", 1)); } if (s.Match(@"\s*limit\s+\d+")) { limit = Convert.ToInt32(s.Scan(@"\s*limit\s+(\d+)\s*", 1)); } // skip can be before or after limit command if (s.Match(@"\s*skip\s+\d+")) { skip = Convert.ToInt32(s.Scan(@"\s*skip\s+(\d+)\s*", 1)); } return(new KeyValuePair <int, int>(skip, limit)); }
public IEnumerable <BsonValue> Execute(StringScanner s, LiteEngine engine) { var col = this.ReadCollection(engine, s); var field = s.Scan(this.FieldPattern).Trim().ThrowIfEmpty("Invalid field/index name", s); var unique = false; string expression = null; s.Scan(@"\s*"); if (s.HasTerminated == false) { unique = s.Scan(@"unique\s*").Length > 0; if (s.Scan(@"\s*using\s+(.+)").Length > 0) { expression = BsonExpression.ReadExpression(s, true, false)?.Source; } } s.ThrowIfNotFinish(); yield return(engine.EnsureIndex(col, field, unique, expression)); }
public IEnumerable <BsonValue> Execute(StringScanner s, LiteEngine engine) { var fs = new LiteStorage(engine); var id = this.ReadId(s); var filename = s.Scan(@"\s*.*").Trim(); var file = fs.FindById(id); if (file != null) { file.SaveAs(filename); yield return(file.AsDocument); } }
private Query ReadInlineQuery(StringScanner s) { var left = this.ReadOneQuery(s); var oper = s.Scan(@"\s+(and|or)\s+").ToLower().Trim(); // there is no right side if (oper.Length == 0) { return(left); } var right = this.ReadInlineQuery(s); return(oper == "and" ? Query.And(left, right) : Query.Or(left, right)); }
public IEnumerable <BsonValue> Execute(StringScanner s, LiteEngine engine) { var fs = new LiteStorage(engine); var id = this.ReadId(s); var filename = s.Scan(@"\s*.*").Trim(); if (!File.Exists(filename)) { throw new IOException("File " + filename + " not found"); } var file = fs.Upload(id, filename); yield return(file.AsDocument); }
public Query ReadQuery(StringScanner s, bool required) { s.Scan(@"\s*"); if (required && s.HasTerminated) { throw LiteException.SyntaxError(s, "Unexpected finish of line"); } if (s.HasTerminated || s.Match(@"skip\s+\d") || s.Match(@"limit\s+\d") || s.Match(@"include[s]?\s+[\$\w]")) { return(Query.All()); } return(this.ReadInlineQuery(s)); }
public IEnumerable <BsonValue> Execute(StringScanner s, LiteEngine engine) { var col = this.ReadCollection(engine, s); // single document update if (s.Match(@"\s*\{")) { var doc = JsonSerializer.Deserialize(s.ToString()).AsDocument; s.ThrowIfNotFinish(); yield return(engine.Update(col, doc)); } // query update else { // db.colName.update // field = value, // array += valueToAdd, // where _id = 1 // and ... var updates = new List <UpdateData>(); var query = Query.All(); while (!s.HasTerminated) { var path = BsonExpression.ReadExpression(s, true, true).Source; var action = s.Scan(@"\s*\+?=\s*").Trim().ThrowIfEmpty("Invalid operator (support = or +=)", s); var value = this.ReadBsonValue(s); var expr = value == null?BsonExpression.ReadExpression(s, true, false) : null; if (action != "+=" && action != "=") { throw LiteException.SyntaxError(s); } if (value == null && expr == null) { throw LiteException.SyntaxError(s); } updates.Add(new UpdateData { Path = path, Value = value, Expr = expr, Add = action == "+=" }); s.Scan(@"\s*"); if (s.Scan(@",\s*").Length > 0) { continue; } else if (s.Scan(@"where\s*").Length > 0 || s.HasTerminated) { break; } else { throw LiteException.SyntaxError(s); } } if (!s.HasTerminated) { query = this.ReadQuery(s, false); } s.ThrowIfNotFinish(); // execute command var count = 0; 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) { engine.Update(col, doc); count++; } } yield return(count); } }
public IEnumerable <BsonValue> Execute(StringScanner s, LiteEngine engine) { var col = this.ReadCollection(engine, s); // single document update if (s.Match(@"\s*\{")) { var doc = JsonSerializer.Deserialize(s.ToString()).AsDocument; s.ThrowIfNotFinish(); yield return(engine.Update(col, doc)); } // query update else { // db.colName.update // field = value, // array += valueToAdd, // where _id = 1 // and ... var query = Query.All(); var updates = new Update(); while (!s.HasTerminated) { var path = BsonExpression.ReadExpression(s, true, true).Source; var action = s.Scan(@"\s*\+?=\s*").Trim().ThrowIfEmpty("Invalid operator (support = or +=)", s); var value = this.ReadBsonValue(s); var expr = value == null?BsonExpression.ReadExpression(s, true, false)?.Source : null; if (action == "+=" && value != null) { updates.Add(path, value); } else if (action == "+=" && expr != null) { updates.AddExpr(path, expr); } else if (action == "=" && value != null) { updates.Set(path, value); } else if (action == "=" && expr != null) { updates.SetExpr(path, expr); } else { throw LiteException.SyntaxError(s); } s.Scan(@"\s*"); if (s.Scan(@",\s*").Length > 0) { continue; } else if (s.Scan(@"where\s*").Length > 0 || s.HasTerminated) { break; } else { throw LiteException.SyntaxError(s); } } if (!s.HasTerminated) { query = this.ReadQuery(s, false); } s.ThrowIfNotFinish(); yield return(engine.Update(col, query, updates)); } }
public bool IsFileCommand(StringScanner s, string command) { return(s.Scan(@"fs\." + command + @"\s*").Length > 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); } } }
public bool IsCommand(StringScanner s) { return(s.Scan(@"db.info$").Length > 0); }
/// <summary> /// Read collection name from db.(collection).(command) /// </summary> public string ReadCollection(LiteEngine db, StringScanner s) { return(s.Scan(@"db\.([\w-]+)\.\w+\s*", 1)); }
/// <summary> /// Read Id file /// </summary> public string ReadId(StringScanner s) { return(s.Scan(LiteFileInfo.ID_PATTERN.Substring(1, LiteFileInfo.ID_PATTERN.Length - 2))); }