Inheritance: InputFragment
        public override SqlFragment Visit(DbNewInstanceExpression expression)
        {
            Debug.Assert(expression.ResultType.EdmType is CollectionType);

            SelectStatement s = new SelectStatement();

            ColumnFragment c = new ColumnFragment(null, null);
            if (expression.Arguments.Count != 0)
                c.Literal = (LiteralFragment)expression.Arguments[0].Accept(this);
            else
                c.Literal = new LiteralFragment("NULL");
            c.ColumnAlias = "X";
            s.Columns.Add(c);
            return s;
        }
        private SelectStatement VisitInputExpressionEnsureSelect(DbExpression e, string name, TypeUsage type)
        {
            InputFragment fragment = VisitInputExpression(e, name, type);
            if (fragment is SelectStatement) return (fragment as SelectStatement);

            SelectStatement s = new SelectStatement();
            
            // if the fragment is a union then it needs to be wrapped
            if (fragment is UnionFragment)
                (fragment as UnionFragment).Wrap(scope);

            s.From = fragment;
            return s;
        }
 private InputFragment WrapJoinInputIfNecessary(InputFragment fragment, bool isRightPart)
 {
   if (fragment is SelectStatement || fragment is UnionFragment)
   {
     fragment.Wrap(scope);
     fragment.Scoped = true;
   }
   else if (fragment is JoinFragment && isRightPart)
   {
     SelectStatement select = new SelectStatement();
     select.From = fragment;
     select.Name = fragment.Name;
     select.Wrap(scope);
     return select;
   }
   return fragment;
 }
 public SelectStatement WrapIfNotCompatible(SelectStatement select, DbExpressionKind expressionKind)
 {
     if (select.IsCompatible(expressionKind)) return select;
     SelectStatement newSelect = new SelectStatement();
     select.Wrap(scope);
     newSelect.From = select;
     return newSelect;
 }
 public void Visit(SelectStatement f)
 {
 }
    /// <summary>
    /// If input sqlFragment is a group by structure, is flattened to remove some nested correlation queries.
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    private SqlFragment TryFlatteningGroupBy(SqlFragment input)
    { 
      SelectStatement select = null;
      SelectStatement tmpFrag = null, tmpFrag2 = null, tmpFrag3 = null;
      InputFragment table = null;
      string objName = null, colName = null, queryName = null;
      // First part assert is a kind-of structure we are looking for
      tmpFrag = input as SelectStatement;
      if (tmpFrag == null) goto NoChanges;
      tmpFrag = ( tmpFrag ).From as SelectStatement;
      if (tmpFrag == null) goto NoChanges;
      queryName = tmpFrag.Name;
      if (tmpFrag.Columns.Count < 2) goto NoChanges;
      if (!(tmpFrag.Columns[0] is ColumnFragment)) goto NoChanges;
      colName = objName = (tmpFrag.Columns[0] as ColumnFragment).ActualColumnName;
      tmpFrag2 = tmpFrag.From as SelectStatement;
      if (tmpFrag2 == null) goto NoChanges;
      if (tmpFrag2.Columns.Count < 1 || !(tmpFrag2.Columns[0] is ColumnFragment)) goto NoChanges;
      if (string.CompareOrdinal(objName, tmpFrag2.Columns[0].ActualColumnName) != 0) goto NoChanges;
      if (tmpFrag.Columns[1].Literal == null ) goto NoChanges;
      tmpFrag2 = tmpFrag.Columns[1].Literal as SelectStatement;
      if (tmpFrag2 == null) goto NoChanges;
      if ((tmpFrag2.Columns.Count != 1) || !(tmpFrag2.Columns[0].Literal != null)) goto NoChanges;
      tmpFrag3 = tmpFrag2.From as SelectStatement;
      if (tmpFrag3 == null) goto NoChanges;
      table = tmpFrag3.From as InputFragment;
      if (table == null) goto NoChanges;
      FunctionFragment func = tmpFrag2.Columns[0].Literal as FunctionFragment;
      if( tmpFrag3.Columns.Count != 1 || !( tmpFrag3.Columns[ 0 ] is ColumnFragment )) goto NoChanges;
      if (func == null) goto NoChanges;
      // Yes it is the kind-of type we like, then optimize it
      select = new SelectStatement(this);      
      table.Name = null;
      string tableName = null;
      TableFragment t = tmpFrag3.From as TableFragment;
      if (t == null)
        tableName = tmpFrag3.Columns[0].TableName;
      else
        tableName = t.Table;
      select.From = table;
      select.Columns.Add(new ColumnFragment(tableName, colName));
      select.Columns.Add(new ColumnFragment(tableName, "C0")
      {
        ColumnAlias = "C1",
        Literal = new FunctionFragment() {
          Argument = new ColumnFragment(tableName, tmpFrag3.Columns[0].ActualColumnName),
          Distinct = tmpFrag3.IsDistinct,
          Name = func.Name
        }
      });
      select.Wrap(null); 
      select.Name = queryName;
      select.AddGroupBy(select.Columns[0]);
      (input as SelectStatement).From = select;
NoChanges:
      return input;
    }
    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);
          }
          newColSelect.Limit = applySel.Limit;
          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);
      }
      return select;
    }
    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;
    }
Exemple #9
0
        List <ColumnFragment> GetDefaultColumnsForFragment(InputFragment input)
        {
            List <ColumnFragment> columns = new List <ColumnFragment>();

            if (input is TableFragment)
            {
                return(GetDefaultColumnsForTable(input as TableFragment));
            }
            else if (input is JoinFragment || input is UnionFragment)
            {
                Debug.Assert(input.Left != null);
                if (input is UnionFragment)
                {
                    generator.Ops.Push(OpType.Union);
                }
                columns = GetDefaultColumnsForFragment(input.Left);
                if (input is JoinFragment && input.Right != null)
                {
                    List <ColumnFragment> right = GetDefaultColumnsForFragment(input.Right);
                    columns.AddRange(right);
                }
                if (input is UnionFragment)
                {
                    generator.Ops.Pop();
                }
            }
            else if (input is SelectStatement)
            {
                SelectStatement select = input as SelectStatement;
                foreach (ColumnFragment cf in select.Columns)
                {
                    ColumnFragment newColumn = new ColumnFragment(cf.TableName,
                                                                  string.IsNullOrEmpty(cf.ColumnAlias) ? cf.ActualColumnName : cf.ColumnAlias
                                                                  );
                    if (generator.GetTopOp() == OpType.Join)
                    {
                        newColumn.ColumnAlias = cf.ColumnAlias;
                        newColumn.PushInput(cf.ColumnName);
                        if (cf.TableName != null)
                        {
                            newColumn.PushInput(cf.TableName);
                        }
                    }
                    else
                    {
                        newColumn.PushInput(cf.ActualColumnName);
                        if (cf.TableName != null && cf.ColumnAlias == null)
                        {
                            newColumn.PushInput(cf.TableName);
                        }
                    }
                    if (select.Name != null)
                    {
                        newColumn.PushInput(select.Name); // add the scope
                    }
                    columns.Add(newColumn);
                }
                return(columns);
            }
            else
            {
                throw new NotImplementedException();
            }
            if (!String.IsNullOrEmpty(input.Name) && input.Name != From.Name)
            {
                foreach (ColumnFragment c in columns)
                {
                    c.PushInput(input.Name);
                }
            }
            return(columns);
        }