protected InFragment TryMergeTwoBinaryFragments(BinaryFragment left, BinaryFragment right) { if ((left.IsNegated == right.IsNegated) && (!left.IsNegated) && (left.Operator == "=") && (right.Operator == "=")) { ColumnFragment cf; LiteralFragment lf; GetBinaryFragmentPartsForIn(left, out lf, out cf); if ((lf != null) && (cf != null)) { ColumnFragment cf2; LiteralFragment lf2; GetBinaryFragmentPartsForIn(right, out lf2, out cf2); if ((lf2 != null) && (cf2 != null) && cf.Equals(cf2)) { InFragment inf = new InFragment(); inf.Argument = cf; inf.InList.Add(lf); inf.InList.Add(lf2); return(inf); } } } return(null); }
protected virtual SqlFragment VisitBinaryExpression(DbExpression left, DbExpression right, string op) { // Optimization: try to use 'like' instead of 'locate' (Edm.IndexOf) for these // cases: (like 'word%'), (like '%word') & (like '%word%'). LikeFragment like = TryPromoteToLike(left, right, op); if (like != null) { return(like); } // normal flow BinaryFragment f = new BinaryFragment(); f.Operator = op; f.Left = left.Accept(this); f.WrapLeft = ShouldWrapExpression(left); f.Right = right.Accept(this); f.WrapRight = ShouldWrapExpression(right); // Optimization, try to promote to In expression // NOTE: In EF6, this optimization is already done, we just implement Visit(DbInExpression). #if !EF6 return(TryToPromoteToIn(f)); #else return(f); #endif }
protected void GetBinaryFragmentPartsForIn(BinaryFragment bf, out LiteralFragment lf, out ColumnFragment cf) { cf = bf.Right as ColumnFragment; lf = bf.Left as LiteralFragment; if (lf == null) { lf = bf.Right as LiteralFragment; cf = bf.Left as ColumnFragment; } }
SqlFragment VisitBinaryExpression(DbExpression left, DbExpression right, string op) { BinaryFragment f = new BinaryFragment(); f.Operator = op; f.Left = left.Accept(this); f.WrapLeft = ShouldWrapExpression(left); f.Right = right.Accept(this); f.WrapRight = ShouldWrapExpression(right); return(f); }
protected internal void VisitAndReplaceTableName(SqlFragment sf, string oldTable, string newTable) { BinaryFragment bf = sf as BinaryFragment; ColumnFragment cf = sf as ColumnFragment; if (bf != null) { VisitAndReplaceTableName(bf.Left, oldTable, newTable); VisitAndReplaceTableName(bf.Right, oldTable, newTable); } else if ((cf != null) && (cf.TableName == oldTable)) { cf.TableName = newTable; } }
protected override SqlFragment VisitBinaryExpression(DbExpression left, DbExpression right, string op) { BinaryFragment f = new BinaryFragment(); f.Operator = op; f.Left = left.Accept(this); f.WrapLeft = ShouldWrapExpression(left); if (f.Left is ColumnFragment) { _columnsVisited.Push((( DbPropertyExpression )left).Property); } f.Right = right.Accept(this); if (f.Left is ColumnFragment) { _columnsVisited.Pop(); } f.WrapRight = ShouldWrapExpression(right); return(f); }
protected InFragment TryMergeBinaryFragmentAndInFragment(BinaryFragment bf, InFragment inf) { if (!bf.IsNegated && (bf.Operator == "=")) { ColumnFragment cf; LiteralFragment lf; GetBinaryFragmentPartsForIn(bf, out lf, out cf); if ((lf != null) && (cf != null)) { if (inf.Argument.Equals(cf)) { if (!inf.InList.Contains(lf)) { inf.InList.Add(lf); } return(inf); } } } return(null); }
public void Visit(BinaryFragment f) { }
public override SqlFragment Visit(DbApplyExpression expression) { DbExpressionBinding inputBinding = expression.Input; InputFragment input = VisitInputExpression(inputBinding.Expression, inputBinding.VariableName, inputBinding.VariableType); DbExpressionBinding applyBinding = expression.Apply; InputFragment apply = VisitInputExpression(applyBinding.Expression, applyBinding.VariableName, applyBinding.VariableType); SelectStatement select = new SelectStatement(this); bool isInputSelect = false; if (!(input is TableFragment)) { input.Wrap(scope); isInputSelect = true; } apply.Wrap(scope); select.From = input; select.Wrap(scope); if (apply is SelectStatement) { SelectStatement applySel = apply as SelectStatement; foreach (ColumnFragment f in applySel.Columns) { SelectStatement newColSelect = new SelectStatement(this); newColSelect.From = applySel.From; newColSelect.Where = applySel.Where; if (isInputSelect) { VisitAndReplaceTableName(newColSelect.Where, (input as SelectStatement).From.Name, input.Name, null); } newColSelect.Limit = applySel.Limit; newColSelect.OrderBy = applySel.OrderBy; newColSelect.Skip = applySel.Skip; newColSelect.GroupBy = applySel.GroupBy; newColSelect.IsDistinct = applySel.IsDistinct; newColSelect.Columns.Add(f); newColSelect.Wrap(scope); scope.Add(applySel.From.Name, applySel.From); ColumnFragment newCol = new ColumnFragment(apply.Name, f.ColumnName); newCol.Literal = newColSelect; newCol.PushInput(newCol.ColumnName); newCol.PushInput(apply.Name); select.AddColumn(newCol, scope); if (string.IsNullOrEmpty(newCol.ColumnAlias)) { newColSelect.Name = newCol.ColumnName; newCol.ColumnAlias = newCol.ColumnName; } scope.Remove(newColSelect); } scope.Remove(applySel.From); scope.Remove(apply); } else if (apply is UnionFragment) { UnionFragment uf = apply as UnionFragment; if (uf.Left == null || uf.Right == null) { throw new Exception("Union fragment is not properly formed."); } var left = uf.Left as SelectStatement; var right = uf.Right as SelectStatement; if (left == null || right == null) { throw new NotImplementedException(); } var whereleft = left.Where as BinaryFragment; var whereright = right.Where as BinaryFragment; if (whereleft == null || whereright == null) { throw new NotImplementedException(); } LiteralFragment literalFragmentWhere = null; //checking where left if (whereleft.Left is ColumnFragment && whereleft.Right is ColumnFragment) { // we replace the where part for a dummy one if (whereright.Left is ColumnFragment && whereright.Right is ColumnFragment) { literalFragmentWhere = new LiteralFragment("1 = 1"); } } if (literalFragmentWhere == null) { throw new NotImplementedException(); } var leftouterjoin = new JoinFragment(); leftouterjoin.JoinType = Metadata.GetOperator(DbExpressionKind.LeftOuterJoin); leftouterjoin.Name = apply.Name; // validating that column fragment on the left matches the name // for the input fragment var leftColumnFragment = whereleft.Left as ColumnFragment; if (leftColumnFragment == null) { throw new NotImplementedException(); } if (!leftColumnFragment.TableName.Equals(input.Name)) { new NotImplementedException(); } var conditionJoin = new BinaryFragment(); conditionJoin.Left = whereleft.Left; //update to the new reference var newColumnFragment = whereright.Right as ColumnFragment; if (newColumnFragment != null) { newColumnFragment.TableName = uf.Name; } conditionJoin.Right = newColumnFragment; conditionJoin.Operator = whereleft.Operator; leftouterjoin.Condition = conditionJoin; (uf.Left as SelectStatement).Where = literalFragmentWhere; (uf.Right as SelectStatement).Where = literalFragmentWhere; leftouterjoin.Left = input; leftouterjoin.Right = uf; return(leftouterjoin); } return(select); }
protected virtual SqlFragment TryToPromoteToIn(BinaryFragment bf) { // TODO: Remember Morgan's theorem // Only try to merge if they are OR'ed. if ((bf.Operator == "OR")) { InFragment inf = bf.Left as InFragment; InFragment inf2 = bf.Right as InFragment; if (inf == null) { BinaryFragment bfLeft = bf.Left as BinaryFragment; if (bfLeft == null) { return(bf); } if (inf2 == null) { // try to create a new infragment BinaryFragment bfRight = bf.Right as BinaryFragment; if (bfRight == null) { return(bf); } InFragment inff = TryMergeTwoBinaryFragments(bfLeft, bfRight); if (inff != null) { return(inff); } } else { // try to merge an existing infragment & a binaryfragment. SqlFragment sf = TryMergeBinaryFragmentAndInFragment(bfLeft, inf2); if (sf != null) { return(sf); } } } else if (inf2 == null) { BinaryFragment bfRight = bf.Right as BinaryFragment; if (bfRight == null) { return(bf); } else { // try to merge an existing infragment & a binaryfragment. SqlFragment sf = TryMergeBinaryFragmentAndInFragment(bfRight, inf); if (sf != null) { return(sf); } } } else { // try to merge both InFragments SqlFragment sf = TryMergeTwoInFragments(inf, inf2); if (sf != null) { return(sf); } } } return(bf); }
protected override SqlFragment VisitBinaryExpression(DbExpression left, DbExpression right, string op) { BinaryFragment f = new BinaryFragment(); f.Operator = op; f.Left = left.Accept(this); f.WrapLeft = ShouldWrapExpression(left); if (f.Left is ColumnFragment) { _columnsVisited.Push( (( DbPropertyExpression )left ).Property ); } f.Right = right.Accept(this); if (f.Left is ColumnFragment) { _columnsVisited.Pop(); } f.WrapRight = ShouldWrapExpression(right); return f; }
public override SqlFragment Visit(DbApplyExpression expression) { DbExpressionBinding inputBinding = expression.Input; InputFragment input = VisitInputExpression(inputBinding.Expression, inputBinding.VariableName, inputBinding.VariableType); DbExpressionBinding applyBinding = expression.Apply; InputFragment apply = VisitInputExpression(applyBinding.Expression, applyBinding.VariableName, applyBinding.VariableType); SelectStatement select = new SelectStatement(this); bool isInputSelect = false; if (!(input is TableFragment)) { input.Wrap(scope); isInputSelect = true; } apply.Wrap(scope); select.From = input; select.Wrap(scope); if (apply is SelectStatement) { SelectStatement applySel = apply as SelectStatement; foreach (ColumnFragment f in applySel.Columns) { SelectStatement newColSelect = new SelectStatement(this); newColSelect.From = applySel.From; newColSelect.Where = applySel.Where; if (isInputSelect) { VisitAndReplaceTableName(newColSelect.Where, (input as SelectStatement).From.Name, input.Name, null); } newColSelect.Limit = applySel.Limit; newColSelect.OrderBy = applySel.OrderBy; newColSelect.Skip = applySel.Skip; newColSelect.GroupBy = applySel.GroupBy; newColSelect.IsDistinct = applySel.IsDistinct; newColSelect.Columns.Add(f); newColSelect.Wrap(scope); scope.Add(applySel.From.Name, applySel.From); ColumnFragment newCol = new ColumnFragment(apply.Name, f.ColumnName); newCol.Literal = newColSelect; newCol.PushInput(newCol.ColumnName); newCol.PushInput(apply.Name); select.AddColumn(newCol, scope); if (string.IsNullOrEmpty(newCol.ColumnAlias)) { newColSelect.Name = newCol.ColumnName; newCol.ColumnAlias = newCol.ColumnName; } scope.Remove(newColSelect); } scope.Remove(applySel.From); scope.Remove(apply); } else if (apply is UnionFragment) { UnionFragment uf = apply as UnionFragment; if (uf.Left == null || uf.Right == null) throw new Exception("Union fragment is not properly formed."); var left = uf.Left as SelectStatement; var right = uf.Right as SelectStatement; if (left == null || right == null) throw new NotImplementedException(); var whereleft = left.Where as BinaryFragment; var whereright = right.Where as BinaryFragment; if (whereleft == null || whereright == null) throw new NotImplementedException(); LiteralFragment literalFragmentWhere = null; //checking where left if (whereleft.Left is ColumnFragment && whereleft.Right is ColumnFragment) { // we replace the where part for a dummy one if (whereright.Left is ColumnFragment && whereright.Right is ColumnFragment) { literalFragmentWhere = new LiteralFragment("1 = 1"); } } if (literalFragmentWhere == null) throw new NotImplementedException(); var leftouterjoin = new JoinFragment(); leftouterjoin.JoinType = Metadata.GetOperator(DbExpressionKind.LeftOuterJoin); leftouterjoin.Name = apply.Name; // validating that column fragment on the left matches the name // for the input fragment var leftColumnFragment = whereleft.Left as ColumnFragment; if (leftColumnFragment == null) throw new NotImplementedException(); if (!leftColumnFragment.TableName.Equals(input.Name)) new NotImplementedException(); var conditionJoin = new BinaryFragment(); conditionJoin.Left = whereleft.Left; //update to the new reference var newColumnFragment = whereright.Right as ColumnFragment; if (newColumnFragment != null) { newColumnFragment.TableName = uf.Name; } conditionJoin.Right = newColumnFragment; conditionJoin.Operator = whereleft.Operator; leftouterjoin.Condition = conditionJoin; (uf.Left as SelectStatement).Where = literalFragmentWhere; (uf.Right as SelectStatement).Where = literalFragmentWhere; leftouterjoin.Left = input; leftouterjoin.Right = uf; return leftouterjoin; } return select; }