Exemple #1
0
        protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall,
                                                         BuildInfo buildInfo)
        {
            var sequenceExpr    = methodCall.Arguments[0];
            var sequence        = builder.BuildSequence(new BuildInfo(buildInfo, sequenceExpr));
            var groupingType    = methodCall.Type.GetGenericArgumentsEx()[0];
            var keySelector     = (LambdaExpression)methodCall.Arguments[1].Unwrap();
            var elementSelector = (LambdaExpression)methodCall.Arguments[2].Unwrap();

            if (methodCall.Arguments[0].NodeType == ExpressionType.Call)
            {
                var call = (MethodCallExpression)methodCall.Arguments[0];

                if (call.Method.Name == "Select")
                {
                    var type = ((LambdaExpression)call.Arguments[1].Unwrap()).Body.Type;

                    if (type.IsGenericTypeEx() &&
                        type.GetGenericTypeDefinition() == typeof(ExpressionBuilder.GroupSubQuery <,>))
                    {
                        sequence = new SubQueryContext(sequence);
                    }
                }
            }

            var key      = new KeyContext(buildInfo.Parent, keySelector, sequence);
            var groupSql = builder.ConvertExpressions(key, keySelector.Body.Unwrap(), ConvertFlags.Key);

            if (sequence.Select.Select.IsDistinct ||
                sequence.Select.GroupBy.Items.Count > 0 ||
                groupSql.Any(_ => !(_.Sql is ISqlField || _.Sql is IColumn)))
            {
                sequence = new SubQueryContext(sequence);
                key      = new KeyContext(buildInfo.Parent, keySelector, sequence);
                groupSql = builder.ConvertExpressions(key, keySelector.Body.Unwrap(), ConvertFlags.Key);
            }

            foreach (var sql in groupSql)
            {
                sequence.Select.GroupBy.Expr(sql.Sql);
            }

            foreach (
                var join in
                QueryVisitor.FindOnce <IJoinedTable>(sequence.Select.From).Where(f => f.JoinType == EJoinType.Inner))
            {
                join.IsWeak = false;
            }

            var element = new SelectContext(buildInfo.Parent, elementSelector, sequence /*, key*/);
            var groupBy = new GroupByContext(buildInfo.Parent, sequenceExpr, groupingType, sequence, key, element);

            return(groupBy);
        }
Exemple #2
0
        private SelectQuery(ISelectQuery clone, Dictionary <ICloneableElement, ICloneableElement> objectTree,
                            Predicate <ICloneableElement> doClone)
        {
            objectTree.Add(clone, this);

            SourceID = Interlocked.Increment(ref SourceIDCounter);

            ICloneableElement parentClone;

            if (clone.ParentSelect != null)
            {
                ParentSelect = objectTree.TryGetValue(clone.ParentSelect, out parentClone)
                    ? (ISelectQuery)parentClone
                    : clone.ParentSelect;
            }

            EQueryType = clone.EQueryType;

            if (IsInsert)
            {
                Insert = (IInsertClause)clone.Insert.Clone(objectTree, doClone);
            }
            if (IsUpdate)
            {
                Update = (IUpdateClause)clone.Update.Clone(objectTree, doClone);
            }
            if (IsDelete)
            {
                Delete = (IDeleteClause)clone.Delete.Clone(objectTree, doClone);
            }

            Select  = new SelectClause(this, clone.Select, objectTree, doClone);
            From    = new FromClause(this, clone.From, objectTree, doClone);
            Where   = new WhereClause(this, clone.Where, objectTree, doClone);
            GroupBy = new GroupByClause(this, clone.GroupBy, objectTree, doClone);
            Having  = new WhereClause(this, clone.Having, objectTree, doClone);
            OrderBy = new OrderByClause(this, clone.OrderBy, objectTree, doClone);

            Parameters.AddRange(clone.Parameters.Select(p => (ISqlParameter)p.Clone(objectTree, doClone)));
            IsParameterDependent = clone.IsParameterDependent;

            foreach (var query in QueryVisitor.FindOnce <ISelectQuery>(this).Where(sq => sq.ParentSelect == clone))
            {
                query.ParentSelect = this;
            }
        }
Exemple #3
0
        public override ISelectQuery Finalize(ISelectQuery selectQuery)
        {
            CheckAliases(selectQuery, 30);

            foreach (var parameter in QueryVisitor.FindOnce <ISqlParameter>(selectQuery.Select))
            {
                parameter.IsQueryParameter = false;
            }

            selectQuery = base.Finalize(selectQuery);

            switch (selectQuery.EQueryType)
            {
            case EQueryType.Delete:
                return(GetAlternativeDelete(selectQuery));

            case EQueryType.Update:
                return(GetAlternativeUpdate(selectQuery));

            default:
                return(selectQuery);
            }
        }
Exemple #4
0
        public void SetAliases()
        {
            _aliases = null;

            var objs = new HashSet <IQueryElement>();

            Parameters.Clear();

            foreach (var element in QueryVisitor.FindOnce <IQueryElement>(this))
            {
                switch (element.ElementType)
                {
                case EQueryElementType.SqlParameter:
                {
                    var p = (ISqlParameter)element;

                    if (p.IsQueryParameter)
                    {
                        if (!objs.Contains(element))
                        {
                            objs.Add(element);
                            p.Name = GetAlias(p.Name, "p");
                        }

                        Parameters.Add(p);
                    }
                    else
                    {
                        IsParameterDependent = true;
                    }
                }

                break;

                case EQueryElementType.Column:
                {
                    if (!objs.Contains(element))
                    {
                        objs.Add(element);

                        var c = (IColumn)element;

                        if (c.Alias != "*")
                        {
                            c.Alias = GetAlias(c.Alias, "c");
                        }
                    }
                }

                break;

                case EQueryElementType.TableSource:
                {
                    var table = (ITableSource)element;

                    if (!objs.Contains(table))
                    {
                        objs.Add(table);
                        table.Alias = GetAlias(table.Alias, "t");
                    }
                }

                break;

                case EQueryElementType.SqlQuery:
                {
                    var sql = (ISelectQuery)element;

                    if (sql.HasUnion)
                    {
                        for (var i = 0; i < sql.Select.Columns.Count; i++)
                        {
                            var col = sql.Select.Columns[i];

                            var index = i;
                            sql.Unions.ForEach(
                                node =>
                                {
                                    var union = node.Value.SelectQuery.Select;

                                    objs.Remove(union.Columns[index]);

                                    union.Columns[index].Alias = col.Alias;
                                });
                        }
                    }

                    break;
                }
                }
            }
        }
Exemple #5
0
        public ISelectQuery ProcessParameters()
        {
            if (!IsParameterDependent)
            {
                return(this);
            }

            var query = new QueryVisitor().Convert(
                this,
                e =>
            {
                switch (e.ElementType)
                {
                case EQueryElementType.SqlParameter:
                    {
                        var p = (ISqlParameter)e;

                        if (p.Value == null)
                        {
                            return(new SqlValue(null));
                        }
                    }

                    break;

                case EQueryElementType.ExprExprPredicate:
                    {
                        var ee = (IExprExpr)e;

                        if (ee.EOperator == EOperator.Equal || ee.EOperator == EOperator.NotEqual)
                        {
                            object value1;
                            object value2;

                            var expr1 = ee.Expr1 as ISqlValue;
                            if (expr1 != null)
                            {
                                value1 = expr1.Value;
                            }
                            else
                            {
                                var parameter = ee.Expr1 as ISqlParameter;
                                if (parameter != null)
                                {
                                    value1 = parameter.Value;
                                }
                                else
                                {
                                    break;
                                }
                            }

                            var sqlValue = ee.Expr2 as ISqlValue;
                            if (sqlValue != null)
                            {
                                value2 = sqlValue.Value;
                            }
                            else
                            {
                                var parameter = ee.Expr2 as ISqlParameter;
                                if (parameter != null)
                                {
                                    value2 = parameter.Value;
                                }
                                else
                                {
                                    break;
                                }
                            }

                            var value = Equals(value1, value2);

                            if (ee.EOperator == EOperator.NotEqual)
                            {
                                value = !value;
                            }

                            return(new Expr(new SqlValue(value), SqlQuery.Precedence.Comparison));
                        }
                    }

                    break;

                case EQueryElementType.InListPredicate:
                    return(ConvertInListPredicate((IInList)e));
                }

                return(null);
            });

            if (query == this)
            {
                return(query);
            }

            query.Parameters.Clear();

            foreach (var parameter in QueryVisitor.FindOnce <ISqlParameter>(query).Where(p => p.IsQueryParameter))
            {
                query.Parameters.Add(parameter);
            }

            return(query);
        }
Exemple #6
0
        protected virtual bool BuildCommand <T>(
            DataConnection dataConnection, Expression <Func <T, bool> > deletePredicate, bool delete, IEnumerable <T> source,
            string tableName, string databaseName, string schemaName)
            where T : class
        {
            var table      = dataConnection.MappingSchema.GetEntityDescriptor(typeof(T));
            var sqlBuilder = dataConnection.DataProvider.CreateSqlBuilder();

            Columns = table.Columns
                      .Select(c => new ColumnInfo
            {
                Column = c,
                Name   = (string)sqlBuilder.Convert(c.ColumnName, ConvertType.NameToQueryField)
            })
                      .ToList();

            StringBuilder.Append("MERGE INTO ");
            sqlBuilder.BuildTableName(StringBuilder,
                                      (string)sqlBuilder.Convert(databaseName ?? table.DatabaseName, ConvertType.NameToDatabase),
                                      (string)sqlBuilder.Convert(schemaName ?? table.SchemaName, ConvertType.NameToOwner),
                                      (string)sqlBuilder.Convert(tableName ?? table.TableName, ConvertType.NameToQueryTable));

            StringBuilder
            .AppendLine(" Target")
            ;

            if (!BuildUsing(dataConnection, source))
            {
                return(false);
            }

            StringBuilder
            .AppendLine("ON")
            .AppendLine("(")
            ;

            foreach (var column in Columns.Where(c => c.Column.IsPrimaryKey))
            {
                StringBuilder
                .AppendFormat("\tTarget.{0} = Source.{0} AND", column.Name)
                .AppendLine()
                ;
            }

            StringBuilder.Length -= 4 + Environment.NewLine.Length;

            StringBuilder
            .AppendLine()
            .AppendLine(")")
            ;

            var updateColumns =
                Columns.Where(
                    c =>
                    !c.Column.IsPrimaryKey && (IsIdentitySupported && c.Column.IsIdentity || !c.Column.SkipOnUpdate))
                .ToList();

            if (updateColumns.Count > 0)
            {
                StringBuilder
                .AppendLine("-- update matched rows")
                .AppendLine("WHEN MATCHED THEN")
                .AppendLine("\tUPDATE")
                .AppendLine("\tSET")
                ;

                var maxLen = updateColumns.Max(c => c.Name.Length);

                foreach (var column in updateColumns)
                {
                    StringBuilder
                    .AppendFormat("\t\t{0} ", column.Name)
                    ;

                    StringBuilder.Append(' ', maxLen - column.Name.Length);

                    StringBuilder
                    .AppendFormat("= Source.{0},", column.Name)
                    .AppendLine()
                    ;
                }

                StringBuilder.Length -= 1 + Environment.NewLine.Length;
            }

            var insertColumns =
                Columns.Where(c => IsIdentitySupported && c.Column.IsIdentity || !c.Column.SkipOnInsert).ToList();

            StringBuilder
            .AppendLine()
            .AppendLine("-- insert new rows")
            .Append("WHEN NOT MATCHED ").Append(ByTargetText).AppendLine("THEN")
            .AppendLine("\tINSERT")
            .AppendLine("\t(")
            ;

            foreach (var column in insertColumns)
            {
                StringBuilder.AppendFormat("\t\t{0},", column.Name).AppendLine();
            }

            StringBuilder.Length -= 1 + Environment.NewLine.Length;

            StringBuilder
            .AppendLine()
            .AppendLine("\t)")
            .AppendLine("\tVALUES")
            .AppendLine("\t(")
            ;

            foreach (var column in insertColumns)
            {
                StringBuilder.AppendFormat("\t\tSource.{0},", column.Name).AppendLine();
            }

            StringBuilder.Length -= 1 + Environment.NewLine.Length;

            StringBuilder
            .AppendLine()
            .AppendLine("\t)")
            ;

            if (delete)
            {
                var predicate = "";

                if (deletePredicate != null)
                {
                    var inlineParameters = dataConnection.InlineParameters;

                    try
                    {
                        dataConnection.InlineParameters = true;

                        var q   = dataConnection.GetTable <T>().Where(deletePredicate);
                        var ctx = q.GetContext();
                        var sql = ctx.Select;

                        var tableSet = new HashSet <ISqlTable>();
                        var tables   = new List <ISqlTable>();

                        var fromTable = (ISqlTable)sql.From.Tables.First.Value.Source;

                        foreach (var tableSource in QueryVisitor.FindOnce <ITableSource>(sql.From))
                        {
                            tableSet.Add((ISqlTable)tableSource.Source);
                            tables.Add((ISqlTable)tableSource.Source);
                        }

                        var whereClause = new QueryVisitor().Convert(sql.Where, e =>
                        {
                            if (e.ElementType == EQueryElementType.SqlQuery)
                            {
                            }

                            if (e.ElementType == EQueryElementType.SqlField)
                            {
                                var fld = (ISqlField)e;
                                var tbl = (ISqlTable)fld.Table;

                                if (tbl != fromTable && tableSet.Contains(tbl))
                                {
                                    var tempCopy   = sql.Clone();
                                    var tempTables = new List <ITableSource>();

                                    tempTables.AddRange(QueryVisitor.FindOnce <ITableSource>(tempCopy.From));

                                    var tt = tempTables[tables.IndexOf(tbl)];

                                    tempCopy.Select.Columns.Clear();
                                    tempCopy.Select.Add(((SqlTable)tt.Source).Fields[fld.Name]);

                                    tempCopy.Where.Search.Conditions.Clear();

                                    var keys = tempCopy.From.Tables.First.Value.Source.GetKeys(true);

                                    foreach (ISqlField key in keys)
                                    {
                                        tempCopy.Where.Field(key).Equal.Field(fromTable.Fields[key.Name]);
                                    }

                                    tempCopy.ParentSelect = sql;

                                    return(tempCopy);
                                }
                            }

                            return(e);
                        }).Search.Conditions.ToList();

                        sql.Where.Search.Conditions.Clear();
                        sql.Where.Search.Conditions.AddRange(whereClause);

                        sql.From.Tables.First.Value.Alias = "Target";

                        ctx.SetParameters();

                        var pq =
                            (DataConnection.PreparedQuery)((IDataContext)dataConnection).SetQuery(new QueryContext
                        {
                            SelectQuery   = sql,
                            SqlParameters = sql.Parameters.ToArray()
                        });

                        var cmd = pq.Commands[0];

                        predicate = "AND " + cmd.Substring(cmd.IndexOf("WHERE") + "WHERE".Length);
                    }
                    finally
                    {
                        dataConnection.InlineParameters = inlineParameters;
                    }
                }

                StringBuilder
                .AppendLine("-- delete rows that are in the target but not in the sourse")
                .AppendLine("WHEN NOT MATCHED BY Source {0}THEN".Args(predicate))
                .AppendLine("\tDELETE")
                ;
            }

            return(true);
        }