private static IDbSelectable CreateNewSelectableForWrappingSelect( IDbSelect dbSelect, IDbSelectable selectable, DbReference dbRef, Expression m, IDbObjectFactory dbFactory, UniqueNameGenerator nameGenerator) { if (dbRef == null) { return(selectable); } var oCol = selectable as IDbColumn; if (oCol != null) { return(dbFactory.BuildColumn(dbRef, oCol.GetAliasOrName(), oCol.ValType)); } var oRefCol = selectable as IDbRefColumn; if (oRefCol != null) { return(dbFactory.BuildRefColumn(dbRef, oRefCol.Alias, oRefCol)); } if (selectable is IDbFunc oDbFunc) { if (string.IsNullOrEmpty(oDbFunc.Alias)) { oDbFunc.Alias = nameGenerator.GenerateAlias(dbSelect, oDbFunc.Name, true); } return(dbFactory.BuildColumn(dbRef, oDbFunc.Alias, oDbFunc.ReturnType)); } return(dbFactory.BuildColumn(dbRef, selectable.Alias, typeof(string))); }
private void UpdateSelection(IDbSelect fromSelect, IDbObject selection, DbReference toSelectRef) { var dbList = selection as IEnumerable <DbKeyValue>; if (dbList != null) { foreach (var dbObj in dbList) { UpdateSelection(fromSelect, dbObj, toSelectRef); } return; } var keyValue = selection as DbKeyValue; selection = keyValue != null ? keyValue.Value : selection; var selectable = GetSelectable(fromSelect, selection, toSelectRef); if (keyValue != null) { selectable.Alias = keyValue.Key; } fromSelect.Selection.Add(selectable); }
public void DbRefMapsToOtherDocumentsByOid() { const string databaseName = "NormTests"; var id = ObjectId.NewObjectId(); using (var session = new Session()) { session.Drop<Product>(); session.Drop<ProductReference>(); session.Add(new Product { _id = id, Name = "RefProduct" }); var productReference = new DbReference<Product>(id); session.Add(new ProductReference { Id = ObjectId.NewObjectId(), Name = "FullCart", ProductsOrdered = new[] { productReference } }); } var server = Mongo.Create("mongodb://localhost/" + databaseName); var reference = server.GetCollection<ProductReference>().Find().First(); var product = reference.ProductsOrdered[0].Fetch(() => server); Assert.Equal(id.Value, product._id.Value); }
public virtual IDbSelectable BuildSelectable(DbReference dbRef, string alias = null) { return(new SqlSelectable { Ref = dbRef, Alias = alias, OutputOption = OutputOption }); }
public IDbSelect BuildSelect(DbReference dbReference) { var dbSelect = new SqlSelect { From = dbReference }; dbReference.OwnerSelect = dbSelect; return(dbSelect); }
private Expression VisitParameterInteral(ParameterExpression p, bool ignoreParamStack) { DbReference dbRef = null; if (p.Type.IsAnonymouse() || p.Type.IsGrouping()) { var dbSelect = _state.GetLastSelect(); dbRef = _dbFactory.BuildRef(null); dbRef.OwnerSelect = dbSelect; var collection = p.Type.IsGrouping() ? dbSelect.GroupBys.AsEnumerable() : dbSelect.Selection; foreach (var selectable in collection) { dbRef.RefSelection[selectable.GetAliasOrName()] = selectable; } } if (dbRef == null && !ignoreParamStack && _state.ParamterStack.Count > 0) { var dbRefs = _state.ParamterStack.Peek(); if (dbRefs.ContainsKey(p)) { dbRef = dbRefs[p]; } } // if we can not find the parameter expression in the ParamterStack, // it means this is the first time we translates the parameter, so we // need to look for it in the most recently translated select // this is required because we may not always has select on the top // of the stack, especially we translating arguments for method calls if (dbRef == null) { var dbSelect = _state.GetLastSelect(); var refCol = (_state.ResultStack.Peek() as IDbRefColumn) ?? dbSelect.Selection.OfType <IDbRefColumn>().LastOrDefault(); dbRef = refCol != null ? refCol.Ref : dbSelect.From; } if (dbRef == null) { throw new NullReferenceException(); } _state.ResultStack.Push(dbRef); return(p); }
public virtual IDbColumn BuildColumn( DbReference dbRef, string colName, DbValType type, string alias = null, bool isJoinKey = false) { return(new SqlColumn { Name = colName, Ref = dbRef, ValType = type, Alias = alias, IsJoinKey = isJoinKey, OutputOption = OutputOption }); }
public IDbRefColumn BuildRefColumn(DbReference dbRef, string alias = null, IDbRefColumn fromRefColumn = null) { var refCol = new SqlRefColumn { Ref = dbRef, Alias = alias, RefTo = fromRefColumn }; if (dbRef != null) { dbRef.ReferredRefColumn = refCol; } return(refCol); }
public IDbJoin BuildJoin( DbReference joinTo, IDbSelect dbSelect, IDbBinary condition = null, DbJoinType dbJoinType = DbJoinType.Inner) { var dbJoin = new SqlJoin { To = joinTo, Condition = condition, Type = dbJoinType }; joinTo.OwnerSelect = dbSelect; joinTo.OwnerJoin = dbJoin; return(dbJoin); }
/// update all joins that are related to dbRef to be left outer join /// this is required by method such as Select or GroupBy public static void UpdateJoinType(DbReference dbRef, DbJoinType dbJoinType = DbJoinType.LeftOuter) { var joins = dbRef?.OwnerSelect?.Joins.Where(j => ReferenceEquals(j.To, dbRef)); if (joins == null) { return; } foreach (var dbJoin in joins) { dbJoin.Type = dbJoinType; var relatedRefs = dbJoin.Condition.GetOperands(). Select(op => (op as IDbSelectable)?.Ref). Where(r => r != null && !ReferenceEquals(r, dbJoin.To)); foreach (var relatedRef in relatedRefs) { UpdateJoinType(relatedRef); } } }
private IDbSelectable GetSelectable(IDbSelect fromSelect, IDbObject selection, DbReference toSelectRef) { var dbRef = selection as DbReference; if (dbRef != null) { IDbRefColumn toRefCol = null; if (dbRef.OwnerSelect != fromSelect) { var toSelect = (IDbSelect)toSelectRef.Referee; toRefCol = _dbFactory.BuildRefColumn(dbRef); toSelect.Selection.Add(toRefCol); dbRef = toSelectRef; } var refColumn = _dbFactory.BuildRefColumn(dbRef); refColumn.RefTo = toRefCol; return(refColumn); } var column = selection as IDbColumn; if (column != null) { if (column.Ref.OwnerSelect != fromSelect) { var toSelect = (IDbSelect)toSelectRef.Referee; toSelect.Selection.Add(column); column = _dbFactory.BuildColumn(column); column.Ref = toSelectRef; } return(column); } throw new NotSupportedException(); }
public void DbRefMapsToOtherDocumentsByOid() { var id = ObjectId.NewObjectId(); using (var db = Mongo.Create(TestHelper.ConnectionString())) { db.GetCollection<TestProduct>().Insert(new TestProduct { _id = id, Name = "RefProduct" }); var productReference = new DbReference<TestProduct>(id); db.GetCollection<ProductReference>().Insert(new ProductReference { Id = ObjectId.NewObjectId(), Name = "FullCart", ProductsOrdered = new[] { productReference } }); var reference = db.GetCollection<ProductReference>().Find(new { }).First(); var product = reference.ProductsOrdered[0].Fetch(() => db); Assert.Equal(id.Value, product._id.Value); } }
private static IDbSelectable CreateNewSelectableForWrappingSelect( IDbSelectable selectable, DbReference dbRef, IDbObjectFactory dbFactory) { if (dbRef == null) { return(selectable); } var oCol = selectable as IDbColumn; if (oCol != null) { return(dbFactory.BuildColumn(dbRef, oCol.GetAliasOrName(), oCol.ValType)); } var oRefCol = selectable as IDbRefColumn; if (oRefCol != null) { return(dbFactory.BuildRefColumn(dbRef, oRefCol.Alias, oRefCol)); } return(dbFactory.BuildColumn(dbRef, selectable.Alias, typeof(string))); }
public void DbRefMapsToOtherDocumentsByOid() { var id = ObjectId.NewObjectId(); using (var db = Mongo.Create(TestHelper.ConnectionString())) { db.GetCollection <TestProduct>().Insert(new TestProduct { _id = id, Name = "RefProduct" }); var productReference = new DbReference <TestProduct>(id); db.GetCollection <ProductReference>().Insert(new ProductReference { Id = ObjectId.NewObjectId(), Name = "FullCart", ProductsOrdered = new[] { productReference } }); var reference = db.GetCollection <ProductReference>().Find(new { }).First(); var product = reference.ProductsOrdered[0].Fetch(() => db); Assert.Equal(id.Value, product._id.Value); } }
/// Create a join for the relation /// For parent relation, we create a join that joins to the parent table /// For child relation, we will create a sub select that returns the child table, /// and then joins to the sub select. /// The reason for joining to sub select for child relation, is that we want to be /// able to group on the join key, so that we will not repeat the parent row. private IDbJoin GetOrCreateJoin(EntityRelation relation, DbReference fromRef, IDbRefColumn refCol) { var dbSelect = fromRef.OwnerSelect; var tupleKey = Tuple.Create(dbSelect, relation); if (!relation.IsChildRelation && _state.CreatedJoins.ContainsKey(tupleKey)) { return(_state.CreatedJoins[tupleKey]); } var toEntity = relation.ToEntity; var dbTable = _dbFactory.BuildTable(toEntity); DbReference joinTo; DbReference childRef = null; IDbSelect childSelect = null; // Create the join. For parent join, we just need to join to a Ref to the table // For child relation, we will firstly create a sub select that return the child table // and then join to then sub select if (!relation.IsChildRelation) { var tableAlias = _nameGenerator.GenerateAlias(dbSelect, dbTable.TableName); joinTo = _dbFactory.BuildRef(dbTable, tableAlias); } else { childRef = _dbFactory.BuildRef(dbTable); childSelect = _dbFactory.BuildSelect(childRef); childRef.Alias = _nameGenerator.GenerateAlias(childSelect, dbTable.TableName); var tableAlias = _nameGenerator.GenerateAlias(dbSelect, TranslationConstants.SubSelectPrefix, true); joinTo = _dbFactory.BuildRef(childSelect, tableAlias); } var dbJoin = _dbFactory.BuildJoin(joinTo, dbSelect); dbSelect.Joins.Add(dbJoin); // build join condition IDbBinary condition = null; for (var i = 0; i < relation.FromKeys.Count; i++) { var fromKey = relation.FromKeys[i]; var toKey = relation.ToKeys[i]; var fromColumn = _dbFactory.BuildColumn(fromRef, fromKey.DbName, fromKey.ValType); var toColumn = _dbFactory.BuildColumn(joinTo, toKey.DbName, toKey.ValType); // If we have created a sub for child relation, we need to the columns // that are used in join condition selected from the sub select. if (childRef != null && childSelect != null) { var alias = _nameGenerator.GenerateAlias(childSelect, toKey.DbName + TranslationConstants.JoinKeySuffix, true); var childColumn = _dbFactory.BuildColumn(childRef, toKey.DbName, toKey.ValType, alias, true); /** * We need to also put the join key in the group of the sub select. * This is to make sure the sub select is grouped by the key so that * the parent (outer select) will not be repeated * This operation needs to happen here not in the aggregation method call. * The reason is that in aggregtion method calls we do not know which column * from the entity is used in relation, so they will not be able to create * the correct column */ childSelect.Selection.Add(_dbFactory.BuildRefColumn(childRef)); childSelect.Selection.Add(childColumn); childSelect.GroupBys.Add(childColumn); toColumn.Name = alias; toColumn.Alias = string.Empty; } // if the relation is found on a fromRef which is referring a sub-select, // it means the from key of the join is not on a table but a derived select. // In this case, we need to add the from key into the derived select, as we will // be using it in the join if (fromRef.Referee is IDbSelect) { var alias = _nameGenerator.GenerateAlias(dbSelect, toKey.DbName + TranslationConstants.JoinKeySuffix, true); fromColumn.Name = alias; fromColumn.Alias = string.Empty; // try to recursively add the join key to all connected sub select. refCol.RefTo?.AddToReferedSelect(_dbFactory, fromKey.DbName, fromKey.ValType, alias); } var binary = _dbFactory.BuildBinary(fromColumn, DbOperator.Equal, toColumn); condition = condition.UpdateBinary(binary, _dbFactory); } dbJoin.Condition = condition; // all relations need to follow the join type if (fromRef.OwnerJoin != null) { dbJoin.Type = fromRef.OwnerJoin.Type; } if (relation.IsChildRelation) { dbJoin.Type = DbJoinType.LeftOuter; } return(_state.CreatedJoins[tupleKey] = dbJoin); }
public IDbColumn BuildColumn( DbReference dbRef, string colName, Type type, string alias = null, bool isJoinKey = false) { return(BuildColumn(dbRef, colName, BuildType(type), alias, isJoinKey)); }