Esempio n. 1
0
        private void AddTablesForPagedCollection <T>(
            SelectQuery <T> selectQuery,
            StringBuilder innerTableSql,
            StringBuilder outerTableSql,
            StringBuilder innerColumnSql,
            StringBuilder outerColumnSql,
            FetchNode rootNode) where T : class, new()
        {
            innerTableSql.Append(" from ");
            this.Dialect.AppendQuotedTableName(innerTableSql, this.Configuration.GetMap <T>());
            innerTableSql.Append(" as t");

            if (selectQuery.IsForUpdate)
            {
                this.Dialect.AppendForUpdateUsingTableHint(innerTableSql);
            }

            // go through the tree and generate the sql
            var signatureBuilder = new StringBuilder();
            var splitOns         = new List <string>();

            foreach (var node in rootNode.Children)
            {
                var signature = this.AddNodeForPagedCollection(node.Value, innerTableSql, outerTableSql, innerColumnSql, outerColumnSql, false);
                if (node.Value.IsFetched)
                {
                    signatureBuilder.Append(signature.Signature);
                    splitOns.AddRange(signature.SplitOn);
                }
            }

            rootNode.FetchSignature = signatureBuilder.ToString();
            rootNode.SplitOn        = string.Join(",", splitOns);
        }
Esempio n. 2
0
        private static FetchNode InnerClone(FetchNode progenitor, FetchNode parent)
        {
            var clone = new FetchNode {
                Alias = progenitor.Alias,
                ContainedCollectionfetchesCount = progenitor.ContainedCollectionfetchesCount,
                FetchSignature    = progenitor.FetchSignature,
                InferredInnerJoin = progenitor.InferredInnerJoin,
                IsFetched         = progenitor.IsFetched,
                SplitOn           = progenitor.SplitOn,
                Column            = progenitor.Column,
                Parent            = parent
            };

            clone.Root = parent?.Root ?? clone;

            var clonedChildren = new OrderedDictionary <string, FetchNode>();

            foreach (var keyValue in progenitor.Children)
            {
                clonedChildren.Add(keyValue.Key, InnerClone(keyValue.Value, clone));
            }

            clone.Children = clonedChildren;
            return(clone);
        }
Esempio n. 3
0
        private string GetOrderClauseInner <T>(
            OrderClause <T> clause,
            FetchNode rootNode,
            Func <IColumn, FetchNode, string> aliasRewriter,
            Func <IColumn, FetchNode, string> nameRewriter,
            out bool isRootPrimaryKeyClause)
        {
            var lambdaExpression = clause.Expression as LambdaExpression;

            if (lambdaExpression == null)
            {
                throw new InvalidOperationException("OrderBy clauses must be LambdaExpressions");
            }

            var node = this.VisitExpression(lambdaExpression.Body, rootNode);
            var sb   = new StringBuilder();

            if (node == null)
            {
                var column = this.configuration.GetMap <T>().Columns[((MemberExpression)lambdaExpression.Body).Member.Name];
                this.dialect.AppendQuotedName(sb, nameRewriter != null ? nameRewriter(column, node) : column.DbName);
                sb.Append(" ").Append(clause.Direction == ListSortDirection.Ascending ? "asc" : "desc");
                isRootPrimaryKeyClause = column.IsPrimaryKey;
            }
            else
            {
                IColumn column = null;
                if (ReferenceEquals(node, rootNode))
                {
                    column = this.configuration.GetMap <T>().Columns[((MemberExpression)lambdaExpression.Body).Member.Name];
                    isRootPrimaryKeyClause = column.IsPrimaryKey;
                }
                else
                {
                    if (node.Column.Relationship == RelationshipType.ManyToOne)
                    {
                        column = node.Column.ParentMap.Columns[((MemberExpression)lambdaExpression.Body).Member.Name];
                    }
                    else if (node.Column.Relationship == RelationshipType.OneToOne)
                    {
                        column = node.Column.OppositeColumn.Map.Columns[((MemberExpression)lambdaExpression.Body).Member.Name];
                    }
                    else
                    {
                        throw new NotSupportedException();
                    }

                    isRootPrimaryKeyClause = false;
                }

                sb.Append(aliasRewriter != null ? aliasRewriter(column, node) : node.Alias).Append(".");
                this.dialect.AppendQuotedName(sb, nameRewriter != null ? nameRewriter(column, node) : column.DbName);
                sb.Append(" ").Append(clause.Direction == ListSortDirection.Ascending ? "asc" : "desc");
            }

            return(sb.ToString());
        }
Esempio n. 4
0
        protected void AddNode(FetchNode node, StringBuilder tableSql)
        {
            var map = this.GetMapForNode(node);

            this.AddTableSqlForNode(node, map, tableSql);
            foreach (var child in node.Children)
            {
                this.AddNode(child.Value, tableSql);
            }
        }
Esempio n. 5
0
        private void AppendDefaultOrderBy <T>(FetchNode rootNode, StringBuilder orderSql, string alias = null, string name = null)
        {
            orderSql.Append(" order by ");
            if (rootNode != null)
            {
                orderSql.Append(alias ?? rootNode.Alias);
                orderSql.Append('.');
            }

            this.Dialect.AppendQuotedName(orderSql, name ?? this.Configuration.GetMap <T>().PrimaryKey.DbName);
        }
Esempio n. 6
0
        public FetchNode AddChild(IColumn column, bool isFetched)
        {
            // create the node
            var newNode = new FetchNode {
                Alias = "t_" + (isFetched
                                                                ? ++this.Root.aliasCounter
                                                                : ++this.Root.nonFetchedAliasCounter),
                IsFetched = isFetched,
                Parent    = this,
                Root      = this.Root,
                Column    = column
            };

            if (column.Relationship == RelationshipType.OneToMany)
            {
                // go through and increase the number of contained collections in each parent node
                var parent = this;
                while (parent != null)
                {
                    ++parent.ContainedCollectionfetchesCount;
                    parent = parent.Parent;
                }
            }

            // insert it
            if (this.Children.Any())
            {
                var i        = 0;
                var inserted = false;
                foreach (var child in this.Children)
                {
                    if (child.Value.Column.FetchId > newNode.Column.FetchId)
                    {
                        this.Children.Insert(i, new KeyValuePair <string, FetchNode>(column.Name, newNode));
                        inserted = true;
                        break;
                    }

                    ++i;
                }

                if (!inserted)
                {
                    this.Children.Add(column.Name, newNode);
                }
            }
            else
            {
                this.Children.Add(column.Name, newNode);
            }

            return(newNode);
        }
Esempio n. 7
0
        protected AddNodeResult AddNode(FetchNode node, StringBuilder tableSql, StringBuilder columnSql, bool selectQueryFetchAllProperties, bool isProjectedQuery)
        {
            // add this node and then it's children
            // add table sql
            var map = this.GetMapForNode(node);

            this.AddTableSqlForNode(node, map, tableSql);

            // add the columns
            var splitOns = new List <string>();

            if (node.IsFetched)
            {
                var columns = GetColumnsWithIncludesAndExcludes(node.IncludedColumns, node.ExcludedColumns, map, selectQueryFetchAllProperties, isProjectedQuery);
                columns = columns.Where(
                    c => !node.Children.ContainsKey(c.Name) || !node.Children[c.Name]
                    .IsFetched);
                foreach (var columnEntry in columns.AsSmartEnumerable())
                {
                    columnSql.Append(", ");
                    this.AddColumn(columnSql, columnEntry.Value, node.Alias);
                    if (columnEntry.IsFirst)
                    {
                        splitOns.Add(columnEntry.Value.Name);
                    }
                }
            }

            // add its children
            var signatureBuilder = new StringBuilder();

            foreach (var child in node.Children)
            {
                var signature = this.AddNode(child.Value, tableSql, columnSql, selectQueryFetchAllProperties, isProjectedQuery);
                if (child.Value.IsFetched)
                {
                    signatureBuilder.Append(signature.Signature);
                    splitOns.AddRange(signature.SplitOn);
                }
            }

            var actualSignature = signatureBuilder.ToString();

            if (node.IsFetched)
            {
                actualSignature = node.Column.FetchId + "S" + actualSignature + "E";
            }

            return(new AddNodeResult {
                Signature = actualSignature,
                SplitOn = splitOns
            });
        }
Esempio n. 8
0
 private void GetOrCreateCurrentNode(PropertyInfo propInfo, Type declaringType)
 {
     this.currentFetchStack.Add(propInfo);
     if (!this.currentNode.Children.ContainsKey(propInfo.Name))
     {
         this.currentNode = this.currentNode.AddChild(this.config.GetMap(declaringType).Columns[propInfo.Name], false);
     }
     else
     {
         this.currentNode = this.currentNode.Children[propInfo.Name];
     }
 }
Esempio n. 9
0
        private ISqlElement VisitParameter(ParameterExpression exp)
        {
            if (this.isTopOfBinaryOrMethod)
            {
                this.isEntityFetch   = true;
                this.entityFetchType = exp.Type;
                return(new ColumnElement(this.modifiedRootNode, this.config.GetMap(exp.Type).PrimaryKey.DbName, true));
            }

            this.currentNode = this.modifiedRootNode;
            return(null);
        }
Esempio n. 10
0
        public void ParseExpression <TBase>(Expression expression, FetchNode rootNode, bool isInclude)
        {
            var lambda = expression as LambdaExpression;

            if (lambda == null)
            {
                throw new InvalidOperationException("Include and Exclude expressions must be LambdaExpressions");
            }

            var  node = this.VisitExpression(lambda.Body, rootNode);
            IMap map;

            if (ReferenceEquals(node, rootNode))
            {
                map = this.configuration.GetMap <TBase>();
            }
            else
            {
                if (node.Column.Relationship == RelationshipType.ManyToOne)
                {
                    map = node.Column.ParentMap;
                }
                else if (node.Column.Relationship == RelationshipType.OneToOne)
                {
                    map = node.Column.OppositeColumn.Map;
                }
                else
                {
                    throw new NotSupportedException("Include/Exclude clauses can only use Many to One and One to One relationships");
                }
            }

            var column = map.Columns[((MemberExpression)lambda.Body).Member.Name];

            if (column.Relationship != RelationshipType.None)
            {
                throw new NotSupportedException("Include/Exclude clauses must end with a property that is a non-relationship type property e.g. a string");
            }

            if (isInclude && node.IncludedColumns == null)
            {
                node.IncludedColumns = new List <IColumn>();
            }
            else if (!isInclude && node.ExcludedColumns == null)
            {
                node.ExcludedColumns = new List <IColumn>();
            }

            (isInclude
                 ? node.IncludedColumns
                 : node.ExcludedColumns).Add(column);
        }
Esempio n. 11
0
        private bool HasAnyNullableAncestor(FetchNode node)
        {
            if (node.Column == null)
            {
                return(false);
            }

            if (node.Column.IsNullable && !node.InferredInnerJoin)
            {
                return(true);
            }

            return(this.HasAnyNullableAncestor(node.Parent));
        }
Esempio n. 12
0
        private string GetMultiTableDeleteQuery <T>(StringBuilder whereSql, FetchNode rootNode)
        {
            var map = this.Configuration.GetMap <T>();
            var sql = new StringBuilder();

            sql.Append("delete t from ");
            this.Dialect.AppendQuotedTableName(sql, map);
            sql.Append(" as t");

            foreach (var node in rootNode.Children)
            {
                this.AddNode(node.Value, sql);
            }

            sql.Append(whereSql);
            return(sql.ToString());
        }
Esempio n. 13
0
        private void AddTablesForNoPagingUnion <T>(
            SelectQuery <T> selectQuery,
            StringBuilder outerQueryColumnSql,
            StringBuilder[] subQueryColumnSqls,
            StringBuilder[] subQueryTableSqls,
            FetchNode rootNode) where T : class, new()
        {
            foreach (var subQuery in subQueryTableSqls)
            {
                subQuery.Append(" from ");
                this.Dialect.AppendQuotedTableName(subQuery, this.Configuration.GetMap <T>());
                subQuery.Append(" as t");

                if (selectQuery.IsForUpdate)
                {
                    this.Dialect.AppendForUpdateUsingTableHint(subQuery);
                }
            }

            // go through the tree and generate the sql
            var signatureBuilder       = new StringBuilder();
            var splitOns               = new List <string>();
            var insideQueryN           = 0;
            var hasSeenFirstCollection = false;

            foreach (var node in rootNode.Children)
            {
                var signature = this.AddNodeForNonPagedUnion(
                    node.Value,
                    outerQueryColumnSql,
                    subQueryColumnSqls,
                    subQueryTableSqls,
                    ref insideQueryN,
                    false,
                    ref hasSeenFirstCollection);
                if (node.Value.IsFetched)
                {
                    signatureBuilder.Append(signature.Signature);
                    splitOns.AddRange(signature.SplitOn);
                }
            }

            rootNode.FetchSignature = signatureBuilder.ToString();
            rootNode.SplitOn        = string.Join(",", splitOns);
        }
Esempio n. 14
0
        public SelectWriterResult GenerateSql <T>(IEnumerable <Expression <Func <T, bool> > > whereClauses, FetchNode rootNode)
        {
            if (whereClauses.IsEmpty())
            {
                return(new SelectWriterResult(string.Empty, null, rootNode));
            }

            this.InitVariables();
            this.modifiedRootNode = rootNode;

            foreach (var whereClause in whereClauses)
            {
                this.VisitWhereClause(whereClause);
                this.sqlElements.Enqueue(new StringElement(" and "));
            }

            return(new SelectWriterResult(this.GetSql(), this.parameters, this.modifiedRootNode));
        }
Esempio n. 15
0
        private void GetOrCreateCurrentNode(PropertyInfo propInfo, Type declaringType)
        {
            if (!this.currentNode.Children.ContainsKey(propInfo.Name))
            {
                // create the node
                var newNode = new FetchNode {
                    Alias     = "t_" + ++this.aliasCounter,
                    IsFetched = false,
                    Parent    = this.currentNode,
                    Column    = this.config.GetMap(declaringType).Columns[propInfo.Name]
                };
                if (this.currentNode.Children.Any())
                {
                    var i        = 0;
                    var inserted = false;
                    foreach (var child in this.currentNode.Children)
                    {
                        if (child.Value.Column.FetchId > newNode.Column.FetchId)
                        {
                            this.currentNode.Children.Insert(i, new KeyValuePair <string, FetchNode>(propInfo.Name, newNode));
                            inserted = true;
                            break;
                        }

                        ++i;
                    }

                    if (!inserted)
                    {
                        this.currentNode.Children.Add(propInfo.Name, newNode);
                    }
                }
                else
                {
                    this.currentNode.Children.Add(propInfo.Name, newNode);
                }

                this.currentNode = newNode;
            }
            else
            {
                this.currentNode = this.currentNode.Children[propInfo.Name];
            }
        }
Esempio n. 16
0
        private void EnsureRootNodeExists()
        {
            if (this.modifiedRootNode == null)
            {
                this.modifiedRootNode = new FetchNode();

                // update exising ISqlElements to use new rootnode (and alias)
                foreach (var element in this.sqlElements)
                {
                    var columnElement = element as ColumnElement;
                    if (columnElement != null && columnElement.IsRoot)
                    {
                        columnElement.Node = this.modifiedRootNode;
                    }
                }

                this.currentNode = this.modifiedRootNode;
            }
        }
Esempio n. 17
0
        private IMap GetMapForNode(FetchNode node)
        {
            IMap map;

            if (node.Column.Relationship == RelationshipType.OneToMany)
            {
                map = this.Configuration.GetMap(node.Column.Type.GetGenericArguments()[0]);
            }
            else if (node.Column.Relationship == RelationshipType.ManyToOne || node.Column.Relationship == RelationshipType.OneToOne)
            {
                map = this.Configuration.GetMap(node.Column.Type);
            }
            else
            {
                throw new NotSupportedException();
            }

            return(map);
        }
Esempio n. 18
0
        public string GetOrderClause <T>(
            OrderClause <T> clause,
            FetchNode rootNode,
            Func <IColumn, FetchNode, string> aliasRewriter,
            Func <IColumn, FetchNode, string> nameRewriter,
            out bool isRootPrimaryKeyClause)
        {
            if (aliasRewriter == null)
            {
                throw new ArgumentNullException("aliasRewriter");
            }

            if (nameRewriter == null)
            {
                throw new ArgumentNullException("nameRewriter");
            }

            return(this.GetOrderClauseInner(clause, rootNode, aliasRewriter, nameRewriter, out isRootPrimaryKeyClause));
        }
Esempio n. 19
0
        public bool AddOrderByClause <T>(
            Queue <OrderClause <T> > orderClauses,
            StringBuilder sql,
            FetchNode rootNode,
            Func <IColumn, FetchNode, string> aliasRewriter = null,
            Func <IColumn, FetchNode, string> nameRewriter  = null)
        {
            if (orderClauses.Count == 0)
            {
                return(false);
            }

            sql.Append(" order by ");
            var orderClauseWriter            = new OrderClauseWriter(this.Configuration, this.Dialect);
            var containsRootPrimaryKeyClause = false;

            while (orderClauses.Count > 0)
            {
                var isRootPrimaryKeyClause = false;
                if (aliasRewriter == null && nameRewriter == null)
                {
                    sql.Append(orderClauseWriter.GetOrderClause(orderClauses.Dequeue(), rootNode, out isRootPrimaryKeyClause));
                }
                else
                {
                    sql.Append(
                        orderClauseWriter.GetOrderClause(orderClauses.Dequeue(), rootNode, aliasRewriter, nameRewriter, out isRootPrimaryKeyClause));
                }

                if (orderClauses.Count > 0)
                {
                    sql.Append(", ");
                }

                if (isRootPrimaryKeyClause)
                {
                    containsRootPrimaryKeyClause = true;
                }
            }

            return(containsRootPrimaryKeyClause);
        }
Esempio n. 20
0
        private void AddTableSqlForNode(FetchNode node, IMap map, StringBuilder tableSql)
        {
            // if this is a non-nullable relationship and we've not already done a left join on the way to this node
            // we can do an inner join
            tableSql.Append(
                node.InferredInnerJoin || (!node.Column.IsNullable && node.Column.Relationship != RelationshipType.OneToMany && !this.HasAnyNullableAncestor(node.Parent))
                    ? " inner join "
                    : " left join ");
            this.Dialect.AppendQuotedTableName(tableSql, map);
            tableSql.Append(" as " + node.Alias);

            if (node.Column.Relationship == RelationshipType.ManyToOne || node.Column.Relationship == RelationshipType.OneToOne)
            {
                tableSql.Append(" on " + node.Parent.Alias + "." + node.Column.DbName + " = " + node.Alias + "." + map.PrimaryKey.DbName);
            }
            else if (node.Column.Relationship == RelationshipType.OneToMany)
            {
                tableSql.Append(" on " + node.Parent.Alias + "." + node.Column.Map.PrimaryKey.DbName + " = " + node.Alias + "." + node.Column.ChildColumn.DbName);
            }
        }
Esempio n. 21
0
        private void AddPropertiesToFetchTree <T>(
            ref int aliasCounter,
            ref int numberCollectionFetches,
            Stack <string> entityNames,
            FetchNode currentNode,
            FetchNode rootNode)
        {
            while (entityNames.Count > 0)
            {
                var propName = entityNames.Pop();

                // don't add duplicates
                if (!currentNode.Children.ContainsKey(propName))
                {
                    var column =
                        this.configuration.GetMap(
                            currentNode == rootNode
                                ? typeof(T)
                                : (currentNode.Column.Relationship == RelationshipType.OneToMany
                                       ? currentNode.Column.Type.GetGenericArguments().First()
                                       : currentNode.Column.Type)).Columns[propName];
                    if (column.IsIgnored)
                    {
                        //TODO we should probably warn at this point
                        continue;
                    }

                    if (column.Relationship == RelationshipType.OneToMany)
                    {
                        ++numberCollectionFetches;
                    }

                    // add to tree
                    currentNode = currentNode.AddChild(column, true);
                }
                else
                {
                    currentNode = currentNode.Children[propName];
                }
            }
        }
Esempio n. 22
0
        public SqlWriterResult GenerateBulkSql <T>(Action <T> updateAction, IEnumerable <Expression <Func <T, bool> > > predicates)
            where T : class, new()
        {
            var predicateArray = predicates as Expression <Func <T, bool> >[] ?? predicates?.ToArray();

            // add where clause
            var       whereSql   = new StringBuilder();
            var       parameters = new AutoNamingDynamicParameters();
            FetchNode rootNode   = null;

            if (predicateArray != null)
            {
                this.AddWhereClause(predicateArray, whereSql, parameters, ref rootNode);
            }

            // run the update
            var entity = new T();

            ((ISetLogger)entity).EnableSetLogging();
            updateAction(entity);

            // find the set properties
            var setLogger = (ISetLogger)entity;
            var setProps  = setLogger.GetSetProperties();

            if (!setProps.Any())
            {
                return(new SqlWriterResult(string.Empty, parameters));
            }

            if (rootNode == null)
            {
                // the where clauses on are on the root table
                return(new SqlWriterResult(this.GetSimpleUpdateQuery(setProps, entity, parameters, whereSql), parameters));
            }

            // cross table where clause
            return(new SqlWriterResult(this.GetMultiTableUpdateQuery(setProps, entity, parameters, whereSql, rootNode), parameters));
        }
Esempio n. 23
0
        public SqlWriterResult GenerateBulkSql <T>(IEnumerable <Expression <Func <T, bool> > > predicates)
        {
            var predicateArray = predicates as Expression <Func <T, bool> >[] ?? predicates?.ToArray();

            // add where clause
            var       whereSql   = new StringBuilder();
            var       parameters = new AutoNamingDynamicParameters();
            FetchNode rootNode   = null;

            if (predicateArray != null)
            {
                this.AddWhereClause(predicateArray, whereSql, parameters, ref rootNode);
            }

            if (rootNode == null)
            {
                // the where clauses were all on the root table
                return(new SqlWriterResult(this.GetSimpleDeleteQuery <T>(whereSql), parameters));
            }

            // cross table where clause
            return(new SqlWriterResult(this.GetMultiTableDeleteQuery <T>(whereSql, rootNode), parameters));
        }
Esempio n. 24
0
        protected FetchNode VisitExpression(Expression expr, FetchNode rootNode)
        {
            var memberExpr = expr as MemberExpression;

            if (memberExpr == null)
            {
                throw new InvalidOperationException("Order/Include/Exclude clauses must contain MemberExpressions");
            }

            if (memberExpr.Expression.NodeType == ExpressionType.Parameter)
            {
                // we're at the bottom
                return(rootNode); // this should be the root node
            }

            // not at the bottom, find the child and return that
            var parentNode = this.VisitExpression(memberExpr.Expression, rootNode);

            if (parentNode == null)
            {
                throw new InvalidOperationException("You must Fetch a relationship if you want to use it in an order by or include/exclude clause");
            }

            var baseExpr = memberExpr.Expression as MemberExpression;

            if (baseExpr == null)
            {
                throw new InvalidOperationException("Order/Include/Exclude clauses must contain MemberExpressions");
            }

            if (!parentNode.Children.ContainsKey(baseExpr.Member.Name))
            {
                throw new InvalidOperationException($"You must Fetch {baseExpr.Member.Name} if you wish to you it in an Order/Include/Exclude clause");
            }

            return(parentNode.Children[baseExpr.Member.Name]);
        }
Esempio n. 25
0
        private FetchNode VisitOrderClause(Expression expr, FetchNode rootNode)
        {
            var memberExpr = expr as MemberExpression;

            if (memberExpr == null)
            {
                throw new InvalidOperationException("OrderBy clauses must contain MemberExpressions");
            }

            if (memberExpr.Expression.NodeType == ExpressionType.Parameter)
            {
                // we're at the bottom
                return(rootNode);
            }
            // we're not at the bottom, find the child and return that
            var parentNode = this.VisitOrderClause(memberExpr.Expression, rootNode);

            if (parentNode == null)
            {
                throw new InvalidOperationException("You must Fetch a relationship if you wish to OrderBy it");
            }

            var baseExpr = memberExpr.Expression as MemberExpression;

            if (baseExpr == null)
            {
                throw new InvalidOperationException("OrderBy clauses must contain MemberExpressions");
            }

            if (!parentNode.Children.ContainsKey(baseExpr.Member.Name))
            {
                throw new InvalidOperationException("You must Fetch a relationship if you wish to OrderBy it");
            }

            return(parentNode.Children[baseExpr.Member.Name]);
        }
Esempio n. 26
0
 private static void AppendPagedUnionJoin(FetchNode node, StringBuilder subQuery)
 {
     if (node.Column.Relationship == RelationshipType.ManyToOne)
     {
         subQuery.Append(" on ")
         .Append(node.Parent.Alias)
         .Append(".")
         .Append(node.Column.DbName)
         .Append(" = ")
         .Append(node.Alias)
         .Append(".")
         .Append(node.Column.ParentMap.PrimaryKey.DbName);
     }
     else if (node.Column.Relationship == RelationshipType.OneToOne)
     {
         subQuery.Append(" on ")
         .Append(node.Parent.Alias)
         .Append(".")
         .Append(node.Column.Map.PrimaryKey.DbName)
         .Append(" = ")
         .Append(node.Alias)
         .Append(".")
         .Append(node.Column.OppositeColumn.DbName);
     }
     else
     {
         subQuery.Append(" on ")
         .Append(node.Parent.Alias)
         .Append(".")
         .Append(node.Column.Map.PrimaryKey.DbName)
         .Append(" = ")
         .Append(node.Alias)
         .Append(".")
         .Append(node.Column.ChildColumn.DbName);
     }
 }
Esempio n. 27
0
 public SelectWriterResult(string sql, DynamicParameters parameters, FetchNode fetchTree)
     : base(sql, parameters) {
     this.FetchTree = fetchTree;
 }
Esempio n. 28
0
 public string GetOrderClause <T>(OrderClause <T> clause, FetchNode rootNode, out bool isRootPrimaryKeyClause)
 {
     return(this.GetOrderClauseInner(clause, rootNode, null, null, out isRootPrimaryKeyClause));
 }
Esempio n. 29
0
        private void AddPropertiesToFetchTree <T>(
            ref int aliasCounter,
            ref int numberCollectionFetches,
            Stack <string> entityNames,
            FetchNode currentNode,
            FetchNode rootNode)
        {
            while (entityNames.Count > 0)
            {
                var propName = entityNames.Pop();

                // don't add duplicates
                if (!currentNode.Children.ContainsKey(propName))
                {
                    var column =
                        this.configuration.GetMap(
                            currentNode == rootNode
                                ? typeof(T)
                                : (currentNode.Column.Relationship == RelationshipType.OneToMany
                                       ? currentNode.Column.Type.GetGenericArguments().First()
                                       : currentNode.Column.Type)).Columns[propName];
                    if (column.IsIgnored)
                    {
                        //TODO we should probably warn at this point
                        continue;
                    }

                    if (column.Relationship == RelationshipType.OneToMany)
                    {
                        ++numberCollectionFetches;
                    }

                    // add to tree
                    var node = new FetchNode {
                        Parent = currentNode, Column = column, Alias = "t_" + ++aliasCounter, IsFetched = true
                    };
                    if (column.Relationship == RelationshipType.OneToMany)
                    {
                        // go through and increase the number of contained collections in each parent node
                        var parent = node.Parent;
                        while (parent != null)
                        {
                            ++parent.ContainedCollectionfetchesCount;
                            parent = parent.Parent;
                        }
                    }

                    // insert the node in the correct order (i.e. respecting the FetchId and then all other things that depend on this
                    // should be constant
                    if (currentNode.Children.Any())
                    {
                        var i        = 0;
                        var inserted = false;
                        foreach (var child in currentNode.Children)
                        {
                            if (child.Value.Column.FetchId > column.FetchId)
                            {
                                currentNode.Children.Insert(i, new KeyValuePair <string, FetchNode>(propName, node));
                                inserted = true;
                                break;
                            }

                            i++;
                        }

                        if (!inserted)
                        {
                            currentNode.Children.Add(propName, node);
                        }
                    }
                    else
                    {
                        currentNode.Children.Add(propName, node);
                    }

                    currentNode = node;
                }
                else
                {
                    currentNode = currentNode.Children[propName];
                }
            }
        }
Esempio n. 30
0
        public FetchNode GetFetchTree <T>(SelectQuery <T> selectQuery, out int aliasCounter, out int numberCollectionFetches) where T : class, new()
        {
            FetchNode rootNode = null;

            numberCollectionFetches = 0;
            aliasCounter            = 0;

            if (selectQuery.HasFetches())
            {
                // now we go through the fetches and generate the tree structure
                rootNode = new FetchNode {
                    Alias = "t"
                };
                foreach (var fetch in selectQuery.Fetches)
                {
                    var lambda = fetch as LambdaExpression;
                    if (lambda != null)
                    {
                        var expr        = lambda.Body as MemberExpression;
                        var currentNode = rootNode;
                        var entityNames = new Stack <string>();

                        // TODO Change this so that algorithm only goes through tree once
                        // We go through the fetch expression (backwards)
                        while (expr != null)
                        {
                            entityNames.Push(expr.Member.Name);
                            expr = expr.Expression as MemberExpression;
                        }

                        // Now go through the expression forwards adding in nodes where needed
                        this.AddPropertiesToFetchTree <T>(ref aliasCounter, ref numberCollectionFetches, entityNames, currentNode, rootNode);
                    }
                }

                // now iterate through the collection fetches
                foreach (var collectionFetch in selectQuery.CollectionFetches)
                {
                    var entityNames = new Stack <string>();
                    var currentNode = rootNode;

                    // start at the top of the stack, pop the expression off and do as above
                    for (var i = collectionFetch.Value.Count - 1; i >= 0; i--)
                    {
                        var lambdaExpr = collectionFetch.Value[i] as LambdaExpression;
                        if (lambdaExpr != null)
                        {
                            var expr = lambdaExpr.Body as MemberExpression;
                            while (expr != null)
                            {
                                entityNames.Push(expr.Member.Name);
                                expr = expr.Expression as MemberExpression;
                            }
                        }
                    }

                    // add in the initial fetch many
                    var fetchManyLambda = collectionFetch.Key as LambdaExpression;
                    if (fetchManyLambda != null)
                    {
                        var expr = fetchManyLambda.Body as MemberExpression;
                        while (expr != null)
                        {
                            entityNames.Push(expr.Member.Name);
                            expr = expr.Expression as MemberExpression;
                        }
                    }

                    this.AddPropertiesToFetchTree <T>(ref aliasCounter, ref numberCollectionFetches, entityNames, currentNode, rootNode);
                }
            }

            return(rootNode);
        }
Esempio n. 31
0
        private void AddRootColumns <T>(SelectQuery <T> selectQuery, StringBuilder columnSql, FetchNode rootNode, IDictionary <Type, IList <IColumn> > includes, IDictionary <Type, IList <IColumn> > excludes, bool removeTrailingComma = true)
            where T : class, new()
        {
            var alias = rootNode != null
                            ? rootNode.Alias
                            : null;

            if (selectQuery.Projection == null)
            {
                var columns = GetColumnsWithIncludesAndExcludes(includes, excludes, this.Configuration.GetMap <T>(), selectQuery.FetchAllProperties);
                columns = columns.Where(
                    c => rootNode == null || !rootNode.Children.ContainsKey(c.Name) || !rootNode.Children[c.Name]
                    .IsFetched);
                foreach (var column in columns)
                {
                    this.AddColumn(columnSql, column, alias);
                    columnSql.Append(", ");
                }
            }

            if (removeTrailingComma)
            {
                columnSql.Remove(columnSql.Length - 2, 2);
            }
        }