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)));
        }
Beispiel #2
0
        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)));
        }
Beispiel #5
0
        /// <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);
        }
Beispiel #6
0
        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));
        }
Beispiel #7
0
        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);
            }
        }