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 static void UpdateIncludeSelectAndProcessToNodes( IncludeNode graphNode, IDbSelect includedSelect, IModelInfoProvider infoProvider, IDbObjectFactory dbFactory, UniqueNameGenerator nameGenerator, AbstractMethodTranslator[] addons) { // create temp table var entityRef = includedSelect.GetReturnEntityRef(); var returnTable = (IDbTable)entityRef.Referee; var newIncludedSelect = dbFactory.BuildSelect(returnTable); newIncludedSelect.From.Alias = nameGenerator.GenerateAlias(newIncludedSelect, returnTable.TableName); var tempTableName = TranslationConstants.TempTablePreix + nameGenerator.GenerateAlias(null, returnTable.TableName, true); var tempTable = dbFactory.BuildTempTable(tempTableName, includedSelect); var tempSelect = dbFactory.BuildSelect(tempTable); tempSelect.From.Alias = nameGenerator.GenerateAlias(tempSelect, tempTable.TableName); var joinToTemp = MakeJoin(newIncludedSelect, tempSelect, dbFactory, nameGenerator); var joinTo = joinToTemp.To; newIncludedSelect.Joins.Add(joinToTemp); foreach (var pk in returnTable.PrimaryKeys) { var fromPkCol = dbFactory.BuildColumn(entityRef, pk.Name, pk.ValType); includedSelect.Selection.Add(fromPkCol); var toPkCol = dbFactory.BuildColumn(tempSelect.From, pk.Name, pk.ValType); tempSelect.Selection.Add(toPkCol); tempSelect.GroupBys.Add(toPkCol); toPkCol = dbFactory.BuildColumn(joinTo, pk.Name, pk.ValType); var binary = dbFactory.BuildBinary(fromPkCol, DbOperator.Equal, toPkCol); joinToTemp.Condition = joinToTemp.Condition.UpdateBinary(binary, dbFactory); } var orderCol = dbFactory.BuildColumn(tempSelect.From, tempTable.RowNumberColumnName, typeof(int)); tempSelect.Selection.Add(orderCol); orderCol = dbFactory.BuildColumn(joinTo, tempTable.RowNumberColumnName, typeof(int)); newIncludedSelect.OrderBys.Add(orderCol); graphNode.Select = newIncludedSelect; graphNode.TempTable = tempTable; foreach (var toNode in graphNode.ToNodes) { TranslateGraphNode(toNode, infoProvider, dbFactory, nameGenerator, addons); } }
public static IDbSelect Map( IDbSelect dbSelect, Type returnType, IModelInfoProvider infoProvider, IDbObjectFactory dbFactory, UniqueNameGenerator nameGenerator) { // If the select returns specified columns, it means there is a constructor in Select, // e.g (.Select(d => new { A = d.ABC })) // In this case we do not need to add alias to the end result as where will be one in the select if (dbSelect.Selection.Any(s => !(s is IDbRefColumn))) { return(dbSelect); } var entityInfo = infoProvider.FindEntityInfo(returnType); if (!entityInfo.RequirePropertyNameMapping()) { return(dbSelect); } var alias = nameGenerator.GenerateAlias(dbSelect, TranslationConstants.SubSelectPrefix, true); var newSelectRef = dbFactory.BuildRef(dbSelect, alias); var newSelect = dbFactory.BuildSelect(newSelectRef); foreach (var fieldInfo in entityInfo.Columns) { var column = dbFactory.BuildColumn( newSelectRef, fieldInfo.DbName, fieldInfo.ValType, fieldInfo.PropertyName); newSelect.Selection.Add(column); } return(newSelect); }
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))); }
/// <summary> /// Add selectable into the selection of the select which referred by the ref column. /// If the ref column has a RefTo ref column, this function will also recursively add /// the selectable to RefTo ref columns /// </summary> public static void AddToReferedSelect( this IDbRefColumn refCol, IDbObjectFactory factory, string colName, DbType colType, string alias = null) { if (refCol.RefTo != null) { refCol.RefTo.AddToReferedSelect(factory, colName, colType, alias); colName = alias ?? colName; } var column = factory.BuildColumn(refCol.Ref, colName, colType, alias); var selection = refCol.OwnerSelect.Selection; selection.Remove(refCol); selection.Add(column); }
protected override Expression VisitMember(MemberExpression m) { var expression = Visit(m.Expression); if (expression is ConstantExpression constExpr) { var container = constExpr.Value; var member = m.Member; object value = null; var valueRetrieved = false; switch (member) { case FieldInfo field: value = field.GetValue(container); valueRetrieved = true; break; case PropertyInfo prop: value = prop.GetValue(container, null); valueRetrieved = true; break; } if (valueRetrieved) { var dbObject = _dbFactory.BuildConstant(value, true); _state.ResultStack.Push(dbObject); return(m); } } var typeInfo = m.Type.GetTypeInfo(); if (m.Expression.Type.IsAnonymouse()) { var dbRef = (DbReference)_state.ResultStack.Peek(); if (dbRef.RefSelection.ContainsKey(m.Member.Name)) { var dbObj = dbRef.RefSelection[m.Member.Name]; // pop out the dbRef from the stack, it was the result of // translate a parameter, and it is not required for following translation _state.ResultStack.Pop(); _state.ResultStack.Push(dbObj); return(m); } } if (m.Expression.Type.IsGrouping()) { var dbRef = (DbReference)_state.ResultStack.Pop(); var dbSelect = dbRef.OwnerSelect; if (dbSelect.GroupBys.IsSingleKey) { var kColumn = dbSelect.GroupBys.Single(); _state.ResultStack.Push(kColumn); } else { _state.ResultStack.Push(dbRef); } return(m); } // if the member is a queryable entity, we need to translate it // into a relation, which means a join var entityInfo = _infoProvider.FindEntityInfo(m.Type); if (entityInfo != null) { var dbObj = _state.ResultStack.Pop(); var refCol = dbObj as IDbRefColumn; var fromRef = refCol != null ? refCol.Ref : (DbReference)dbObj; var fromEntity = _infoProvider.FindEntityInfo(m.Expression.Type); var relation = fromEntity.GetRelation(m.Member.Name); var dbJoin = GetOrCreateJoin(relation, fromRef, refCol ?? fromRef.ReferredRefColumn); // RefColumnAlias is used as alias in case we need to create a ref column for this dbRef dbJoin.To.RefColumnAlias = m.Member.Name; if (refCol != null) { refCol = _dbFactory.BuildRefColumn(dbJoin.To, m.Member.Name); if (dbJoin.To.Referee is IDbSelect subSelect) { refCol.RefTo = subSelect.Selection.OfType <IDbRefColumn>().Single(); } _state.ResultStack.Push(refCol); return(m); } _state.ResultStack.Push(relation.IsChildRelation ? dbJoin.To.Referee : dbJoin.To); return(m); } if (typeInfo.Namespace.StartsWith("System")) { var dbObj = _state.ResultStack.Pop(); var refCol = dbObj as IDbRefColumn; var dbRef = refCol != null ? refCol.Ref : (DbReference)dbObj; var fieldInfo = _infoProvider.FindFieldInfo(m.Member); var col = _dbFactory.BuildColumn(dbRef, fieldInfo.DbName, fieldInfo.ValType); _state.ResultStack.Push(col); // if we create a column whose DbRef is using by a RefColumn // we need to make sure the column is added to the ref column's owner select // This normally happen when we are accessing a column from a child relation refCol = refCol ?? dbRef.ReferredRefColumn; // if the ref column is not now, and it is referring another ref column // we need to make sure the column we translated is in the sub select which // owns the ref column that referred by the current refColumn refCol?.RefTo?.AddToReferedSelect(_dbFactory, fieldInfo.DbName, fieldInfo.ValType); return(m); } return(base.VisitMember(m)); }
private static void UpdateFromNodeTempTable( IncludeNode fromNode, IDbObject dbObject, IDbSelect includedSelect, IDbObjectFactory dbFactory, UniqueNameGenerator nameGenerator) { var fromSelect = fromNode.Select; var dbJoin = fromSelect.Joins.Single( j => dbObject is DbReference ? ReferenceEquals(j.To, dbObject) : ReferenceEquals(j.To.Referee, dbObject)); // remove the join to included relation from fromSelect fromSelect.Joins.Remove(dbJoin); if (dbObject is IDbSelect) { var refCol = includedSelect.Selection.Single(c => c is IDbRefColumn); includedSelect.Selection.Remove(refCol); } var keys = dbJoin.Condition.GetDbObjects <IDbColumn>().ToArray(); var fromKeys = keys.Where(c => !ReferenceEquals(c.Ref, dbJoin.To)).ToArray(); var toKeys = keys.Where(c => ReferenceEquals(c.Ref, dbJoin.To)).ToArray(); var tempTable = fromNode.TempTable; var sourceSelect = tempTable.SourceSelect; var fromRef = sourceSelect.GetReturnEntityRef(); var returnRef = includedSelect.GetReturnEntityRef(); var tempSelect = dbFactory.BuildSelect(tempTable); tempSelect.From.Alias = nameGenerator.GenerateAlias(tempSelect, tempTable.TableName); var joinToTemp = MakeJoin(includedSelect, tempSelect, dbFactory, nameGenerator); includedSelect.Joins.Add(joinToTemp); for (var i = 0; i < fromKeys.Length; i++) { var fromKey = fromKeys[i]; var toKey = toKeys[i]; var fromPkCol = dbFactory.BuildColumn(fromRef, fromKey.Name, fromKey.ValType); sourceSelect.Selection.Add(fromPkCol); var tempPkCol = dbFactory.BuildColumn(tempSelect.From, fromKey.Name, fromKey.ValType); tempSelect.Selection.Add(tempPkCol); tempSelect.GroupBys.Add(tempPkCol); if (dbObject is IDbSelect) { var key = toKey; toKey = (IDbColumn)includedSelect.Selection.Single(c => c.GetAliasOrName() == key.GetNameOrAlias()); includedSelect.Selection.Remove(toKey); includedSelect.GroupBys.Remove(toKey); } fromPkCol = dbFactory.BuildColumn(joinToTemp.To, fromKey.Name, fromKey.ValType); var toPkCol = dbFactory.BuildColumn(returnRef, toKey.Name, toKey.ValType); var binary = dbFactory.BuildBinary(toPkCol, DbOperator.Equal, fromPkCol); joinToTemp.Condition = joinToTemp.Condition.UpdateBinary(binary, dbFactory); } }