internal static SqlTableSource CheckTableSource(SqlTableSource ts, ISqlTableSource table, string alias) { if (ts.Source == table && (alias == null || ts.Alias == alias)) { return(ts); } var jt = ts[table, alias]; if (jt != null) { return(jt); } if (ts.Source is SelectQuery) { var s = ((SelectQuery)ts.Source).From[table, alias]; if (s != null) { return(s); } } return(null); }
public SqlJoinedTable(JoinType joinType, SqlTableSource table, bool isWeak, SqlSearchCondition searchCondition) { JoinType = joinType; Table = table; IsWeak = isWeak; Condition = searchCondition; CanConvertApply = true; }
void VisitX(SqlTableSource table) { Visit(table.Source); foreach (var j in table.Joins) { Visit(j); } }
static IEnumerable <ISqlTableSource> GetJoinTables(SqlTableSource source, QueryElementType elementType) { if (source.Source.ElementType == elementType) { yield return(source.Source); } foreach (var join in source.Joins) { foreach (var table in GetJoinTables(join.Table, elementType)) { yield return(table); } } }
SqlTableSource AddOrGetTable(ISqlTableSource table, string?alias) { var ts = GetTable(table, alias); if (ts != null) { return(ts); } var t = new SqlTableSource(table, alias); Tables.Add(t); return(t); }
internal SqlMergeStatement( string?hint, SqlTableSource target, SqlTableLikeSource source, SqlSearchCondition on, IEnumerable <SqlMergeOperationClause> operations) { Hint = hint; Target = target; Source = source; On = on; foreach (var operation in operations) { Operations.Add(operation); } }
static SqlTableSource?FindTableSource(SqlTableSource source, SqlTable table) { if (source.Source == table) { return(source); } foreach (var join in source.Joins) { var ts = FindTableSource(join.Table, table); if (ts != null) { return(ts); } } return(null); }
static SqlTableSource FindField(SqlField field, SqlTableSource table) { if (field.Table == table.Source) { return(table); } foreach (var join in table.Joins) { var t = FindField(field, join.Table); if (t != null) { return(join.Table); } } return(null); }
public static Tuple <SqlTableSource, SqlTableSource> MoveJoinsToSubqueries( this SqlStatement statement, string firstTableAlias, string secondTableAlias, BasicMergeBuilder.QueryElement part) { var baseTablesCount = secondTableAlias == null ? 1 : 2; // collect tables, referenced in FROM clause var tableSet = new HashSet <SqlTable>(); var tables = new List <SqlTable>(); new QueryVisitor().Visit(statement.SelectQuery.From, e => { if (e.ElementType == QueryElementType.TableSource) { var et = (SqlTableSource)e; tableSet.Add((SqlTable)et.Source); tables.Add((SqlTable)et.Source); } }); if (tables.Count > baseTablesCount) { var firstTable = (SqlTable)statement.SelectQuery.From.Tables[0].Source; var secondTable = baseTablesCount > 1 ? (SqlTable)statement.SelectQuery.From.Tables[0].Joins[0].Table.Source : null; ISqlExpressionWalkable queryPart; switch (part) { case BasicMergeBuilder.QueryElement.Where: queryPart = statement.SelectQuery.Where; break; case BasicMergeBuilder.QueryElement.InsertSetter: queryPart = statement.GetInsertClause(); break; case BasicMergeBuilder.QueryElement.UpdateSetter: queryPart = statement.GetUpdateClause(); break; default: throw new InvalidOperationException(); } queryPart.Walk(new WalkOptions(true), element => statement.SelectQuery.ConvertToSubquery(element, tableSet, tables, firstTable, secondTable)); } var table1 = statement.SelectQuery.From.Tables[0]; table1.Alias = firstTableAlias; SqlTableSource table2 = null; if (secondTableAlias != null) { if (tables.Count > baseTablesCount) { table2 = statement.SelectQuery.From.Tables[0].Joins[0].Table; } else { table2 = statement.SelectQuery.From.Tables[1]; } table2.Alias = secondTableAlias; } return(Tuple.Create(table1, table2)); }
IQueryElement?ConvertInternal(IQueryElement?element) { if (element == null) { return(null); } // if element manually added outside to VisistedElements as null, it will be processed continuously. // Useful when we have to duplicate such items, especially parameters var newElement = GetCurrentReplaced(element); if (newElement != null) { return(newElement); } Stack.Add(element); try { switch (element.ElementType) { case QueryElementType.SqlFunction: { var func = (SqlFunction)element; var parms = Convert(func.Parameters); if (parms != null && !ReferenceEquals(parms, func.Parameters)) { newElement = new SqlFunction(func.SystemType, func.Name, func.IsAggregate, func.Precedence, parms); } break; } case QueryElementType.SqlExpression: { var expr = (SqlExpression)element; var parameter = Convert(expr.Parameters); if (parameter != null && !ReferenceEquals(parameter, expr.Parameters)) { newElement = new SqlExpression(expr.SystemType, expr.Expr, expr.Precedence, parameter); } break; } case QueryElementType.SqlBinaryExpression: { var bexpr = (SqlBinaryExpression)element; var expr1 = (ISqlExpression?)ConvertInternal(bexpr.Expr1); var expr2 = (ISqlExpression?)ConvertInternal(bexpr.Expr2); if (expr1 != null && !ReferenceEquals(expr1, bexpr.Expr1) || expr2 != null && !ReferenceEquals(expr2, bexpr.Expr2)) { newElement = new SqlBinaryExpression(bexpr.SystemType, expr1 ?? bexpr.Expr1, bexpr.Operation, expr2 ?? bexpr.Expr2, bexpr.Precedence); } break; } case QueryElementType.SqlTable: { var table = (SqlTable)element; var newTable = (SqlTable)_convert(this, table); if (ReferenceEquals(newTable, table)) { var targs = table.TableArguments == null || table.TableArguments.Length == 0 ? null : Convert(table.TableArguments); if (targs != null && !ReferenceEquals(table.TableArguments, targs)) { var newFields = table.Fields.Values.Select(f => new SqlField(f)); newTable = new SqlTable(table, newFields, targs); } } if (!ReferenceEquals(table, newTable)) { AddVisited(table.All, newTable.All); foreach (var prevField in table.Fields.Values) { if (newTable.Fields.TryGetValue(prevField.Name, out var newField)) { AddVisited(prevField, newField); } } } newElement = newTable; break; } case QueryElementType.SqlCteTable: { var table = (SqlCteTable)element; var newTable = (SqlCteTable)_convert(this, table); if (ReferenceEquals(newTable, table)) { var cte = (CteClause?)ConvertInternal(table.Cte); var ce = cte != null && !ReferenceEquals(table.Cte, cte); if (ce) { var newFields = table.Fields.Values.Select(f => new SqlField(f)); newTable = new SqlCteTable(table, newFields, cte !); } } if (!ReferenceEquals(table, newTable)) { AddVisited(table.All, newTable.All); foreach (var prevField in table.Fields.Values) { if (newTable.Fields.TryGetValue(prevField.Name, out var newField)) { AddVisited(prevField, newField); } } } newElement = newTable; break; } case QueryElementType.Column: { var col = (SqlColumn)element; var expr = (ISqlExpression?)ConvertInternal(col.Expression); if (expr != null && !ReferenceEquals(expr, col.Expression)) { newElement = new SqlColumn(col.Parent, expr, col.RawAlias); } break; } case QueryElementType.TableSource: { var table = (SqlTableSource)element; var source = (ISqlTableSource?)ConvertInternal(table.Source); var joins = Convert(table.Joins); List <ISqlExpression[]>?uk = null; if (table.HasUniqueKeys) { uk = ConvertListArray(table.UniqueKeys, null); } if (source != null && !ReferenceEquals(source, table.Source) || joins != null && !ReferenceEquals(table.Joins, joins)) { newElement = new SqlTableSource( source ?? table.Source, table._alias, joins ?? table.Joins, uk ?? (table.HasUniqueKeys ? table.UniqueKeys : null)); } break; } case QueryElementType.JoinedTable: { var join = (SqlJoinedTable)element; var table = (SqlTableSource?)ConvertInternal(join.Table); var cond = (SqlSearchCondition?)ConvertInternal(join.Condition); if (table != null && !ReferenceEquals(table, join.Table) || cond != null && !ReferenceEquals(cond, join.Condition)) { newElement = new SqlJoinedTable(join.JoinType, table ?? join.Table, join.IsWeak, cond ?? join.Condition); } break; } case QueryElementType.SearchCondition: { var sc = (SqlSearchCondition)element; var conds = Convert(sc.Conditions); if (conds != null && !ReferenceEquals(sc.Conditions, conds)) { newElement = new SqlSearchCondition(conds); } break; } case QueryElementType.Condition: { var c = (SqlCondition)element; var p = (ISqlPredicate?)ConvertInternal(c.Predicate); if (p != null && !ReferenceEquals(c.Predicate, p)) { newElement = new SqlCondition(c.IsNot, p, c.IsOr); } break; } case QueryElementType.ExprPredicate: { var p = (SqlPredicate.Expr)element; var e = (ISqlExpression?)ConvertInternal(p.Expr1); if (e != null && !ReferenceEquals(p.Expr1, e)) { newElement = new SqlPredicate.Expr(e, p.Precedence); } break; } case QueryElementType.NotExprPredicate: { var p = (SqlPredicate.NotExpr)element; var e = (ISqlExpression?)ConvertInternal(p.Expr1); if (e != null && !ReferenceEquals(p.Expr1, e)) { newElement = new SqlPredicate.NotExpr(e, p.IsNot, p.Precedence); } break; } case QueryElementType.ExprExprPredicate: { var p = (SqlPredicate.ExprExpr)element; var e1 = (ISqlExpression?)ConvertInternal(p.Expr1); var e2 = (ISqlExpression?)ConvertInternal(p.Expr2); if (e1 != null && !ReferenceEquals(p.Expr1, e1) || e2 != null && !ReferenceEquals(p.Expr2, e2)) { newElement = new SqlPredicate.ExprExpr(e1 ?? p.Expr1, p.Operator, e2 ?? p.Expr2); } break; } case QueryElementType.LikePredicate: { var p = (SqlPredicate.Like)element; var e1 = (ISqlExpression?)ConvertInternal(p.Expr1); var e2 = (ISqlExpression?)ConvertInternal(p.Expr2); var es = (ISqlExpression?)ConvertInternal(p.Escape); if (e1 != null && !ReferenceEquals(p.Expr1, e1) || e2 != null && !ReferenceEquals(p.Expr2, e2) || es != null && !ReferenceEquals(p.Escape, es)) { newElement = new SqlPredicate.Like(e1 ?? p.Expr1, p.IsNot, e2 ?? p.Expr2, es ?? p.Escape, p.IsSqlLike); } break; } case QueryElementType.BetweenPredicate: { var p = (SqlPredicate.Between)element; var e1 = (ISqlExpression?)ConvertInternal(p.Expr1); var e2 = (ISqlExpression?)ConvertInternal(p.Expr2); var e3 = (ISqlExpression?)ConvertInternal(p.Expr3); if (e1 != null && !ReferenceEquals(p.Expr1, e1) || e2 != null && !ReferenceEquals(p.Expr2, e2) || e3 != null && !ReferenceEquals(p.Expr3, e3)) { newElement = new SqlPredicate.Between(e1 ?? p.Expr1, p.IsNot, e2 ?? p.Expr2, e3 ?? p.Expr3); } break; } case QueryElementType.IsNullPredicate: { var p = (SqlPredicate.IsNull)element; var e = (ISqlExpression?)ConvertInternal(p.Expr1); if (e != null && !ReferenceEquals(p.Expr1, e)) { newElement = new SqlPredicate.IsNull(e, p.IsNot); } break; } case QueryElementType.InSubQueryPredicate: { var p = (SqlPredicate.InSubQuery)element; var e = (ISqlExpression?)ConvertInternal(p.Expr1); var q = (SelectQuery?)ConvertInternal(p.SubQuery); if (e != null && !ReferenceEquals(p.Expr1, e) || q != null && !ReferenceEquals(p.SubQuery, q)) { newElement = new SqlPredicate.InSubQuery(e ?? p.Expr1, p.IsNot, q ?? p.SubQuery); } break; } case QueryElementType.InListPredicate: { var p = (SqlPredicate.InList)element; var e = (ISqlExpression?)ConvertInternal(p.Expr1); var v = Convert(p.Values); if (e != null && !ReferenceEquals(p.Expr1, e) || v != null && !ReferenceEquals(p.Values, v)) { newElement = new SqlPredicate.InList(e ?? p.Expr1, p.IsNot, v ?? p.Values); } break; } case QueryElementType.FuncLikePredicate: { var p = (SqlPredicate.FuncLike)element; var f = (SqlFunction?)ConvertInternal(p.Function); if (f != null && !ReferenceEquals(p.Function, f)) { newElement = new SqlPredicate.FuncLike(f); } break; } case QueryElementType.SetExpression: { var s = (SqlSetExpression)element; var c = (ISqlExpression?)ConvertInternal(s.Column); var e = (ISqlExpression?)ConvertInternal(s.Expression); if (c != null && !ReferenceEquals(s.Column, c) || e != null && !ReferenceEquals(s.Expression, e)) { newElement = new SqlSetExpression(c ?? s.Column, e ?? s.Expression !); } break; } case QueryElementType.InsertClause: { var s = (SqlInsertClause)element; var t = s.Into != null ? (SqlTable?)ConvertInternal(s.Into) : null; var i = Convert(s.Items); if (t != null && !ReferenceEquals(s.Into, t) || i != null && !ReferenceEquals(s.Items, i)) { var sc = new SqlInsertClause { Into = t ?? s.Into }; sc.Items.AddRange(i ?? s.Items); sc.WithIdentity = s.WithIdentity; newElement = sc; } break; } case QueryElementType.UpdateClause: { var s = (SqlUpdateClause)element; var t = s.Table != null ? (SqlTable?)ConvertInternal(s.Table) : null; var i = Convert(s.Items); var k = Convert(s.Keys); if (t != null && !ReferenceEquals(s.Table, t) || i != null && !ReferenceEquals(s.Items, i) || k != null && !ReferenceEquals(s.Keys, k)) { var sc = new SqlUpdateClause { Table = t ?? s.Table }; sc.Items.AddRange(i ?? s.Items); sc.Keys.AddRange(k ?? s.Keys); newElement = sc; } break; } case QueryElementType.SelectStatement: { var s = (SqlSelectStatement)element; var selectQuery = (SelectQuery?)ConvertInternal(s.SelectQuery); var with = s.With != null ? (SqlWithClause?)ConvertInternal(s.With) : null; var ps = ConvertSafe(s.Parameters); if (ps != null && !ReferenceEquals(s.Parameters, ps) || selectQuery != null && !ReferenceEquals(s.SelectQuery, selectQuery) || with != null && !ReferenceEquals(s.With, with)) { newElement = new SqlSelectStatement(selectQuery ?? s.SelectQuery); ((SqlSelectStatement)newElement).Parameters.AddRange(ps ?? s.Parameters); ((SqlSelectStatement)newElement).With = with ?? s.With; CorrectQueryHierarchy(((SqlSelectStatement)newElement).SelectQuery); } break; } case QueryElementType.InsertStatement: { var s = (SqlInsertStatement)element; var selectQuery = (SelectQuery? )ConvertInternal(s.SelectQuery); var insert = (SqlInsertClause?)ConvertInternal(s.Insert); var with = s.With != null ? (SqlWithClause?)ConvertInternal(s.With) : null; var ps = ConvertSafe(s.Parameters); if (insert != null && !ReferenceEquals(s.Insert, insert) || ps != null && !ReferenceEquals(s.Parameters, ps) || selectQuery != null && !ReferenceEquals(s.SelectQuery, selectQuery) || with != null && !ReferenceEquals(s.With, with)) { newElement = new SqlInsertStatement(selectQuery ?? s.SelectQuery) { Insert = insert ?? s.Insert }; ((SqlInsertStatement)newElement).Parameters.AddRange(ps ?? s.Parameters); ((SqlInsertStatement)newElement).With = with ?? s.With; CorrectQueryHierarchy(((SqlInsertStatement)newElement).SelectQuery); } break; } case QueryElementType.UpdateStatement: { var s = (SqlUpdateStatement)element; var selectQuery = (SelectQuery? )ConvertInternal(s.SelectQuery); var update = (SqlUpdateClause?)ConvertInternal(s.Update); var with = s.With != null ? (SqlWithClause?)ConvertInternal(s.With) : null; var ps = ConvertSafe(s.Parameters); if (update != null && !ReferenceEquals(s.Update, update) || ps != null && !ReferenceEquals(s.Parameters, ps) || selectQuery != null && !ReferenceEquals(s.SelectQuery, selectQuery) || with != null && !ReferenceEquals(s.With, with)) { newElement = new SqlUpdateStatement(selectQuery ?? s.SelectQuery) { Update = update ?? s.Update }; ((SqlUpdateStatement)newElement).Parameters.AddRange(ps ?? s.Parameters); ((SqlUpdateStatement)newElement).With = with ?? s.With; CorrectQueryHierarchy(((SqlUpdateStatement)newElement).SelectQuery); } break; } case QueryElementType.InsertOrUpdateStatement: { var s = (SqlInsertOrUpdateStatement)element; var selectQuery = (SelectQuery? )ConvertInternal(s.SelectQuery); var insert = (SqlInsertClause?)ConvertInternal(s.Insert); var update = (SqlUpdateClause?)ConvertInternal(s.Update); var with = s.With != null ? (SqlWithClause?)ConvertInternal(s.With) : null; var ps = ConvertSafe(s.Parameters); if (insert != null && !ReferenceEquals(s.Insert, insert) || update != null && !ReferenceEquals(s.Update, update) || ps != null && !ReferenceEquals(s.Parameters, ps) || selectQuery != null && !ReferenceEquals(s.SelectQuery, selectQuery) || with != null && !ReferenceEquals(s.With, with)) { newElement = new SqlInsertOrUpdateStatement(selectQuery ?? s.SelectQuery) { Insert = insert ?? s.Insert, Update = update ?? s.Update }; ((SqlInsertOrUpdateStatement)newElement).Parameters.AddRange(ps ?? s.Parameters); ((SqlInsertOrUpdateStatement)newElement).With = with ?? s.With; CorrectQueryHierarchy(((SqlInsertOrUpdateStatement)newElement).SelectQuery); } break; } case QueryElementType.DeleteStatement: { var s = (SqlDeleteStatement)element; var selectQuery = s.SelectQuery != null ? (SelectQuery?)ConvertInternal(s.SelectQuery) : null; var table = s.Table != null ? (SqlTable?)ConvertInternal(s.Table) : null; var top = s.Top != null ? (ISqlExpression?)ConvertInternal(s.Top) : null; var with = s.With != null ? (SqlWithClause?)ConvertInternal(s.With) : null; var ps = ConvertSafe(s.Parameters); if (table != null && !ReferenceEquals(s.Table, table) || top != null && !ReferenceEquals(s.Top, top) || ps != null && !ReferenceEquals(s.Parameters, ps) || selectQuery != null && !ReferenceEquals(s.SelectQuery, selectQuery) || with != null && !ReferenceEquals(s.With, with)) { newElement = new SqlDeleteStatement { Table = table ?? s.Table, SelectQuery = selectQuery ?? s.SelectQuery, Top = top ?? s.Top !, IsParameterDependent = s.IsParameterDependent }; ((SqlDeleteStatement)newElement).Parameters.AddRange(ps ?? s.Parameters); ((SqlDeleteStatement)newElement).With = with ?? s.With; CorrectQueryHierarchy(((SqlDeleteStatement)newElement).SelectQuery); } break; } case QueryElementType.CreateTableStatement: { var s = (SqlCreateTableStatement)element; var t = s.Table != null ? (SqlTable?)ConvertInternal(s.Table) : null; var ps = ConvertSafe(s.Parameters); if (t != null && !ReferenceEquals(s.Table, t) || ps != null && !ReferenceEquals(s.Parameters, ps)) { newElement = new SqlCreateTableStatement { Table = t ?? s.Table }; if (ps != null) { ((SqlCreateTableStatement)newElement).Parameters.AddRange(ps); } else { ((SqlCreateTableStatement)newElement).Parameters.AddRange(s.Parameters); } } break; } case QueryElementType.DropTableStatement: { var s = (SqlDropTableStatement)element; var t = s.Table != null ? (SqlTable?)ConvertInternal(s.Table) : null; var ps = ConvertSafe(s.Parameters); if (t != null && !ReferenceEquals(s.Table, t) || ps != null && !ReferenceEquals(s.Parameters, ps)) { newElement = new SqlDropTableStatement(s.IfExists) { Table = t ?? s.Table }; if (ps != null) { ((SqlDropTableStatement)newElement).Parameters.AddRange(ps); } else { ((SqlDropTableStatement)newElement).Parameters.AddRange(s.Parameters); } } break; } case QueryElementType.SelectClause: { var sc = (SqlSelectClause)element; var cols = Convert(sc.Columns, CloneColumn); var take = (ISqlExpression?)ConvertInternal(sc.TakeValue); var skip = (ISqlExpression?)ConvertInternal(sc.SkipValue); if ( cols != null && !ReferenceEquals(sc.Columns, cols) || take != null && !ReferenceEquals(sc.TakeValue, take) || skip != null && !ReferenceEquals(sc.SkipValue, skip)) { newElement = new SqlSelectClause(sc.IsDistinct, take ?? sc.TakeValue, sc.TakeHints, skip ?? sc.SkipValue, cols ?? sc.Columns); ((SqlSelectClause)newElement).SetSqlQuery(sc.SelectQuery); }
public SqlMergeStatement(SqlTable target) { Target = new SqlTableSource(target, TargetAlias); }
public SqlJoinedTable(JoinType joinType, SqlTableSource table, bool isWeak) : this(joinType, table, isWeak, new SqlSearchCondition()) { }