Example #1
0
 protected override object InternalVisit(SelectScalarExpression node)
 {
     return(new Func <Environment, object>(env =>
     {
         return new Func <IResultTable, Selector[]>(table =>
         {
             SQLExpressionInterpreter expressionInterpreter = new SQLExpressionInterpreter(Database);
             var expr = expressionInterpreter.Visit <Func <Environment, object> >(node.Expression);
             var innerEnv = env.NewChild();
             var selector = new Func <IResultRow, object>((row) =>
             {
                 innerEnv.CurrentRow = row;
                 return expr(innerEnv);
             });
             //what about node.ColumnName.Identifier ??
             string name = null;
             if (node.ColumnName != null)
             {
                 name = node.ColumnName.Value;
             }
             else
             {
                 //try to get the column name from the selected expression, if possible.
                 //TODO: if i do a select (3+4) sql server says something like "(no column name)", i am guessing a result column should have a nullable name
                 name = node.ScriptTokenStream[node.LastTokenIndex].Text;
             }
             return new Selector[] { new Selector(name, selector) };
         });
     }));
 }
        internal static bool TryGetOutputColumnName(SelectScalarExpression sscalarExpr, out string columnName)
        {
            if (sscalarExpr.ColumnName != null)
            {
                if (sscalarExpr.ColumnName.ValueExpression != null)
                {
                    throw new NotImplementedException(sscalarExpr.ColumnName.ValueExpression.WhatIsThis());
                }
                else if (sscalarExpr.ColumnName.Identifier != null)
                {
                    columnName = sscalarExpr.ColumnName.Identifier.Dequote();
                    return(true);
                }
                else
                {
                    if (!string.IsNullOrEmpty(sscalarExpr.ColumnName.Value))
                    {
                        columnName = sscalarExpr.ColumnName.Value;
                        return(true);
                    }

                    columnName = null;
                    return(false);
                }
            }
            else
            {
                columnName = null;
                return(false);
            }
        }
Example #3
0
        public override void VisitSelectScalarExpression(SelectScalarExpression selectScalarExpression)
        {
            selectScalarExpression.Expression.Accept(this);
            var    expression = expressionStack.Pop();
            string columnName = selectScalarExpression.Alias ?? nameStack.Pop();

            selectExpressions.Add(new SelectExpression(expression, columnName));
        }
        public override void Visit(SelectScalarExpression node)
        {
            var columnName = node.ColumnName is null ? string.Empty : node.ColumnName.Value;
            var isLiteral  = node.Expression is Literal;

            ReturnValues.Add(new SelectElementWrapper(node, _queryExpressionId, columnName, isLiteral));
            base.Visit(node);
        }
Example #5
0
        public void TestSelectScalarExpressionAccept()
        {
            Mock <KoraliumSqlVisitor> mock = new Mock <KoraliumSqlVisitor>();
            SelectScalarExpression    selectScalarExpression = new SelectScalarExpression();

            selectScalarExpression.Accept(mock.Object);
            mock.Verify(x => x.VisitSelectScalarExpression(selectScalarExpression));
        }
Example #6
0
        public override void ExplicitVisit(SelectScalarExpression node)
        {
            base.ExplicitVisit(node);

            // Keep track of aliases introduced in the SELECT clause so we can ignore them later
            if (!String.IsNullOrEmpty(node.ColumnName?.Identifier?.Value))
            {
                _selectAliases.Add(node.ColumnName.Identifier.Value);
            }
        }
Example #7
0
        public QsiColumnNode VisitSelectScalarExpression(SelectScalarExpression selectScalarExpression)
        {
            QsiExpressionNode      expression = null;
            QsiColumnReferenceNode column     = null;

            if (selectScalarExpression.Expression is ColumnReferenceExpression columnReferenceExpression)
            {
                column = new QsiColumnReferenceNode
                {
                    Name = IdentifierVisitor.CreateQualifiedIdentifier(columnReferenceExpression.MultiPartIdentifier)
                };

                if (selectScalarExpression.ColumnName == null)
                {
                    SqlServerTree.PutFragmentSpan(column, selectScalarExpression);
                    return(column);
                }
            }
            else
            {
                expression = ExpressionVisitor.VisitScalarExpression(selectScalarExpression.Expression);
            }

            return(TreeHelper.Create <QsiDerivedColumnNode>(n =>
            {
                if (column != null)
                {
                    n.Column.SetValue(column);
                }
                else if (expression != null)
                {
                    n.Expression.SetValue(expression);
                }

                var columnName = selectScalarExpression.ColumnName;

                if (columnName != null)
                {
                    if (columnName.Identifier == null)
                    {
                        n.Alias.SetValue(new QsiAliasNode
                        {
                            Name = new QsiIdentifier(columnName.Value, false)
                        });
                    }
                    else
                    {
                        n.Alias.SetValue(CreateAliasNode(columnName.Identifier));
                    }
                }

                SqlServerTree.PutFragmentSpan(n, selectScalarExpression);
            }));
        }
            public override void Visit(SelectScalarExpression node)
            {
                base.Visit(node);

                var identifier = new IdentifierVisitor();

                node.Accept(identifier);

                this.SelectNodes.Add(
                    String.Join(".", identifier.SelectNodes.Select(x => x.Value)
                                ));
            }
        public void TestVisitSelectScalarExpression()
        {
            Mock <ScalarExpression> mock = new Mock <ScalarExpression>();
            SelectScalarExpression  selectScalarExpression = new SelectScalarExpression()
            {
                Expression = mock.Object
            };

            KoraliumSqlVisitor koraliumSqlVisitor = new KoraliumSqlVisitor();

            koraliumSqlVisitor.Visit(selectScalarExpression);

            mock.Verify(x => x.Accept(koraliumSqlVisitor));
        }
        public void TestSelectScalarExpressionEquals()
        {
            SelectScalarExpression first = new SelectScalarExpression()
            {
                Alias      = "test",
                Expression = new StringLiteral()
                {
                    Value = "t"
                }
            };

            SelectScalarExpression firstClone = new SelectScalarExpression()
            {
                Alias      = "test",
                Expression = new StringLiteral()
                {
                    Value = "t"
                }
            };

            SelectScalarExpression second = new SelectScalarExpression()
            {
                Alias      = "test2",
                Expression = new StringLiteral()
                {
                    Value = "t"
                }
            };

            SelectScalarExpression third = new SelectScalarExpression()
            {
                Alias      = "test",
                Expression = new StringLiteral()
                {
                    Value = "t2"
                }
            };

            //Equals
            Assert.IsTrue(Equals(first, firstClone));
            Assert.IsFalse(Equals(first, null));
            Assert.IsFalse(Equals(first, second));
            Assert.IsFalse(Equals(first, third));
            Assert.IsFalse(Equals(first, "other type"));

            //Hash code
            Assert.AreEqual(first.GetHashCode(), firstClone.GetHashCode());
            Assert.AreNotEqual(first.GetHashCode(), second.GetHashCode());
            Assert.AreNotEqual(first.GetHashCode(), third.GetHashCode());
        }
Example #11
0
        public void TestCloneSelectScalarExpression()
        {
            SelectScalarExpression selectScalarExpression = new SelectScalarExpression()
            {
                Alias      = "test",
                Expression = new StringLiteral()
                {
                    Value = "t"
                }
            };

            var clone = selectScalarExpression.Clone() as SelectScalarExpression;

            Assert.AreEqual(selectScalarExpression, clone);
            Assert.IsFalse(ReferenceEquals(selectScalarExpression, clone));
            Assert.IsFalse(ReferenceEquals(selectScalarExpression.Expression, clone.Expression));
        }
Example #12
0
 public override void ExplicitVisit(SelectScalarExpression node)
 {
     // IIF(@limitreached = 1, 1, 0)
     if (hasSetVariable)
     {
         outputSet.Clear();
     }
     else
     {
         //Console.WriteLine("Resolve type for scalar:" + node.AsText());
         OutputColumnDescriptor columnDbType = resolveColumnType
             ? columnTypeResolver.ResolveSelectScalarExpression(node)
             : null;
         if (columnDbType == null || columnDbType.ColumnType == null)
         {
             // put a breakpoint here
             //this column cannot be resolved from this query. if this is a part of a IF statemt try ELSE branch.
         }
         outputSet.AddColumn(new ProcedureOutputColumn(node, columnDbType)); // SelectScalarExpression
     }
 }
Example #13
0
        public override void ExplicitVisit(SelectScalarExpression node)
        {
            base.ExplicitVisit(node);
            var originalColumn = node.Expression as ColumnReferenceExpression;
            var name           = ReplaceExpression(node, n => n.Expression);

            if (name != null && node.ColumnName == null)
            {
                var alias = name;

                if (originalColumn != null)
                {
                    alias = originalColumn.MultiPartIdentifier.Identifiers.Last().Value;
                }

                node.ColumnName = new IdentifierOrValueExpression {
                    Identifier = new Identifier {
                        Value = alias
                    }
                };
            }
        }
Example #14
0
        /// <summary>
        /// Initializes a new instance of the <see cref="SelectColumn" /> class.
        /// </summary>
        /// <param name="selectScalarExpression">The select scalar expression.</param>
        /// <param name="bodyColumnTypes">The body column types.</param>
        /// <param name="tableAliases">The table aliases.</param>
        /// <param name="outerJoinedTables">The aliases or names of tables that were outer joined. Used to determine if a non-nulllable column could still be null.</param>
        /// <exception cref="System.InvalidOperationException">Could not find column within BodyDependencies:  + fullColName</exception>
        public SelectColumn(SelectScalarExpression selectScalarExpression, IDictionary <string, DataType> bodyColumnTypes, IDictionary <string, string> tableAliases, IEnumerable <string> outerJoinedTables)
        {
            if (selectScalarExpression.Expression is ColumnReferenceExpression)
            {
                var columnReferenceExpression = (ColumnReferenceExpression)selectScalarExpression.Expression;
                var identifiers = columnReferenceExpression.MultiPartIdentifier.Identifiers;
                var fullColName = this.GetFullColumnName(tableAliases, identifiers);

                this.Name = selectScalarExpression.ColumnName != null && selectScalarExpression.ColumnName.Value != null
                    ? selectScalarExpression.ColumnName.Value
                    : identifiers.Last().Value;

                var key = bodyColumnTypes.Keys.FirstOrDefault(x => x.EndsWith(fullColName, StringComparison.InvariantCultureIgnoreCase));
                if (key == null)
                {
                    throw new InvalidOperationException("Could not find column within BodyDependencies: " + fullColName);
                }


                bool outerJoined = false;
                // If the column was defined in the SELECT with the table alias or name, check if the table was outer joined.
                if (identifiers.Count() > 1)
                {
                    var tableAliasOrName = identifiers.ElementAt(identifiers.Count() - 2).Value;
                    outerJoined = outerJoinedTables.Contains(tableAliasOrName);
                }
                else // If the column was defined in the SELECT without any qualification, then there must
                     // be only one column in the list of tables with that name. Look it up in the bodyColumnTypes.
                {
                    var keyParts = key.Split('.');
                    if (keyParts.Count() > 1)
                    {
                        var tableAliasOrName = keyParts.ElementAt(keyParts.Count() - 2);
                        outerJoined = outerJoinedTables.Contains(tableAliasOrName);
                    }
                }

                var bodyColumnType = bodyColumnTypes[key];
                this.DataTypes  = bodyColumnType.Map;
                this.IsNullable = bodyColumnType.Nullable || outerJoined;
            }
            else if (selectScalarExpression.Expression is ConvertCall)
            {
                var convertCall = (ConvertCall)selectScalarExpression.Expression;
                this.Name = selectScalarExpression.ColumnName != null && selectScalarExpression.ColumnName.Value != null
                    ? selectScalarExpression.ColumnName.Value
                    : "Value";
                this.DataTypes  = DataTypeHelper.Instance.GetMap(TypeFormat.SqlServerDbType, convertCall.DataType.Name.BaseIdentifier.Value);
                this.IsNullable = true;
            }
            else if (selectScalarExpression.Expression is CastCall)
            {
                var castCall = (CastCall)selectScalarExpression.Expression;
                this.Name = selectScalarExpression.ColumnName != null && selectScalarExpression.ColumnName.Value != null
                    ? selectScalarExpression.ColumnName.Value
                    : "Value";
                this.DataTypes  = DataTypeHelper.Instance.GetMap(TypeFormat.SqlServerDbType, castCall.DataType.Name.BaseIdentifier.Value);
                this.IsNullable = true;
            }
            else if (selectScalarExpression.Expression is IntegerLiteral)
            {
                var integerLiteral = (IntegerLiteral)selectScalarExpression.Expression;
                this.Name = selectScalarExpression.ColumnName != null && selectScalarExpression.ColumnName.Value != null
                    ? selectScalarExpression.ColumnName.Value
                    : "Value";
                this.DataTypes  = DataTypeHelper.Instance.GetMap(TypeFormat.SqlServerDbType, "int");
                this.IsNullable = true;
            }
            else if (selectScalarExpression.Expression is VariableReference)
            {
                var variableReference = (VariableReference)selectScalarExpression.Expression;
                this.Name       = variableReference.Name.TrimStart('@');
                this.DataTypes  = DataTypeHelper.Instance.GetMap(TypeFormat.DotNetFrameworkType, "Object");
                this.IsNullable = true;
            }
            else
            {
                this.Name = selectScalarExpression.ColumnName != null && selectScalarExpression.ColumnName.Value != null
                    ? selectScalarExpression.ColumnName.Value
                    : "Value";
                this.DataTypes  = DataTypeHelper.Instance.GetMap(TypeFormat.DotNetFrameworkType, "Object");
                this.IsNullable = true;
            }
        }
Example #15
0
 public virtual void VisitSelectScalarExpression(SelectScalarExpression selectScalarExpression)
 {
     Visit(selectScalarExpression.Expression);
     //DONE
 }
Example #16
0
        /// <summary>
        /// Initializes a new instance of the <see cref="SelectColumn" /> class.
        /// </summary>
        /// <param name="selectScalarExpression">The select scalar expression.</param>
        /// <param name="bodyColumnTypes">The body column types.</param>
        /// <param name="tableAliases">The table aliases.</param>
        /// <param name="outerJoinedTables">The aliases or names of tables that were outer joined. Used to determine if a non-nulllable column could still be null.</param>
        /// <exception cref="System.InvalidOperationException">Could not find column within BodyDependencies:  + fullColName</exception>
        public SelectColumn(SelectScalarExpression selectScalarExpression, IDictionary<string, DataType> bodyColumnTypes, IDictionary<string, string> tableAliases, IEnumerable<string> outerJoinedTables)
        {
            if (selectScalarExpression.Expression is ColumnReferenceExpression)
            {
                var columnReferenceExpression = (ColumnReferenceExpression)selectScalarExpression.Expression;
                var identifiers = columnReferenceExpression.MultiPartIdentifier.Identifiers;
                var fullColName = this.GetFullColumnName(tableAliases, identifiers);

                this.Name = selectScalarExpression.ColumnName != null && selectScalarExpression.ColumnName.Value != null
                    ? selectScalarExpression.ColumnName.Value
                    : identifiers.Last().Value;

                var key = bodyColumnTypes.Keys.FirstOrDefault(x => x.EndsWith(fullColName, StringComparison.InvariantCultureIgnoreCase));
                if (key == null) throw new InvalidOperationException("Could not find column within BodyDependencies: " + fullColName);

                bool outerJoined = false;
                // If the column was defined in the SELECT with the table alias or name, check if the table was outer joined.
                if (identifiers.Count() > 1)
                {
                    var tableAliasOrName = identifiers.ElementAt(identifiers.Count() - 2).Value;
                    outerJoined = outerJoinedTables.Contains(tableAliasOrName);
                }
                else // If the column was defined in the SELECT without any qualification, then there must
                    // be only one column in the list of tables with that name. Look it up in the bodyColumnTypes.
                {
                    var keyParts = key.Split('.');
                    if (keyParts.Count() > 1)
                    {
                        var tableAliasOrName = keyParts.ElementAt(keyParts.Count() - 2);
                        outerJoined = outerJoinedTables.Contains(tableAliasOrName);
                    }
                }

                var bodyColumnType = bodyColumnTypes[key];
                this.DataTypes = bodyColumnType.Map;
                this.IsNullable = bodyColumnType.Nullable || outerJoined;
            }
            else if (selectScalarExpression.Expression is ConvertCall)
            {
                var convertCall = (ConvertCall)selectScalarExpression.Expression;
                this.Name = selectScalarExpression.ColumnName != null && selectScalarExpression.ColumnName.Value != null
                    ? selectScalarExpression.ColumnName.Value
                    : "Value";
                this.DataTypes = DataTypeHelper.Instance.GetMap(TypeFormat.SqlServerDbType, convertCall.DataType.Name.BaseIdentifier.Value);
                this.IsNullable = true;
            }
            else if (selectScalarExpression.Expression is CastCall)
            {
                var castCall = (CastCall)selectScalarExpression.Expression;
                this.Name = selectScalarExpression.ColumnName != null && selectScalarExpression.ColumnName.Value != null
                    ? selectScalarExpression.ColumnName.Value
                    : "Value";
                this.DataTypes = DataTypeHelper.Instance.GetMap(TypeFormat.SqlServerDbType, castCall.DataType.Name.BaseIdentifier.Value);
                this.IsNullable = true;
            }
            else if (selectScalarExpression.Expression is IntegerLiteral)
            {
                var integerLiteral = (IntegerLiteral)selectScalarExpression.Expression;
                this.Name = selectScalarExpression.ColumnName != null && selectScalarExpression.ColumnName.Value != null
                    ? selectScalarExpression.ColumnName.Value
                    : "Value";
                this.DataTypes = DataTypeHelper.Instance.GetMap(TypeFormat.SqlServerDbType, "int");
                this.IsNullable = true;
            }
            else if (selectScalarExpression.Expression is VariableReference)
            {
                var variableReference = (VariableReference)selectScalarExpression.Expression;
                this.Name = variableReference.Name.TrimStart('@');
                this.DataTypes = DataTypeHelper.Instance.GetMap(TypeFormat.DotNetFrameworkType, "Object");
                this.IsNullable = true;
            }
            else
            {
                this.Name = selectScalarExpression.ColumnName != null && selectScalarExpression.ColumnName.Value != null
                    ? selectScalarExpression.ColumnName.Value
                    : "Value";
                this.DataTypes = DataTypeHelper.Instance.GetMap(TypeFormat.DotNetFrameworkType, "Object");
                this.IsNullable = true;
            }
        }
Example #17
0
 public override void Visit(SelectScalarExpression node) { this.action(node); }
 public override void ExplicitVisit(SelectScalarExpression fragment)
 {
     _fragments.Add(fragment);
 }
 public gsColumnParserSelectScalar(SelectElement element)
     : base(element)
 {
     _Expression = element as SelectScalarExpression;
 }
 public override void VisitSelectScalarExpression(SelectScalarExpression selectScalarExpression)
 {
     selectScalarExpression.Expression.Accept(this);
     ColumnName = selectScalarExpression.Alias ?? nameStack.Pop();
 }
 public override void ExplicitVisit(SelectScalarExpression node)
 {
     base.ExplicitVisit(node);
 }
        public OutputColumnDescriptor ResolveSelectScalarExpression(SelectScalarExpression node)
        {
            IQueryModel model = EnsureModel();

            if (TryGetOutputColumnName(node, out string outputColumnName))
            {
                if (model.TryGetQueryOutputColumnByName(batchResolver, outputColumnName, out QueryColumnBase col))
                {
                    return(ColumnModelToDescriptor(col));
                }

                throw new NotImplementedException(node.Expression.WhatIsThis());
            }
            else if (node.Expression is ColumnReferenceExpression colRef)
            {
                if (TryColumnReference(model, colRef, out QueryColumnBase col))
                {
                    return(ColumnModelToDescriptor(col));
                }

                throw new NotImplementedException(node.Expression.WhatIsThis());
            }
            else if (node.Expression is IIfCall iif)
            {
                // no output name! if single column output -> use it???
                if (TrtGetAnonymousColumnType_ScalarExpression(iif.ThenExpression, out DbType columnDbTypeT, out bool allowNull))
                {
                    return(ColumnModelToDescriptor(columnDbTypeT, allowNull));
                }
                if (TrtGetAnonymousColumnType_ScalarExpression(iif.ThenExpression, out DbType columnDbTypeE, out allowNull))
                {
                    return(ColumnModelToDescriptor(columnDbTypeE, allowNull));
                }
                throw new NotImplementedException(iif.ElseExpression.WhatIsThis());
            }
            else if (node.Expression is CastCall castExpr)
            {
                var dbType = ProcedureGenerator.ResolveToDbDataType(castExpr.DataType);
                return(ColumnModelToDescriptor(dbType, true));
            }
            else if (node.Expression is VariableReference varRefExpr)
            {
                var varType = batchResolver.TryGetScalarVariableType(varRefExpr.Name);
                if (varType != null)
                {
                    return(ColumnModelToDescriptor(varType.ColumnDbType, varType.AllowNull));
                }
                throw new NotImplementedException(varRefExpr.Name);
            }
            else if (node.Expression is FunctionCall fCall)
            {
                string functionName = fCall.FunctionName.Dequote();
                if (string.Equals(functionName, "COUNT", StringComparison.OrdinalIgnoreCase))
                {
                    return(ColumnModelToDescriptor(DbType.Int32, true));
                }

                throw new NotImplementedException(fCall.WhatIsThis());
            }
            else
            {
                throw new NotImplementedException(node.Expression.WhatIsThis());
            }
        }
Example #23
0
        private void ProcessViewStatementBody(TSqlStatement sqlStatement)
        {
            ViewStatementBody aViewStatementBody = (ViewStatementBody)sqlStatement;

            AddLogText("Columns:");
            foreach (Identifier aColumnIdentifier in aViewStatementBody.Columns)
            {
                AddLogText(string.Format("Column:{0}", aColumnIdentifier.Value));
                aColumnInfoList.ColumnList.Add(new ColumnInfo {
                    Alias = aColumnIdentifier.Value
                });
            }

            AddLogText("");
            AddLogText("QueryExpression SelectElements:");
            SelectStatement aSelectStatement = aViewStatementBody.SelectStatement;
            QueryExpression aQueryExpression = aSelectStatement.QueryExpression;

            if (aQueryExpression.GetType() == typeof(QuerySpecification))
            {
                QuerySpecification aQuerySpecification = (QuerySpecification)aQueryExpression;
                int aSelectElementID = 0;
                foreach (SelectElement aSelectElement in aQuerySpecification.SelectElements)
                {
                    if (aSelectElement.GetType() == typeof(SelectScalarExpression))
                    {
                        SelectScalarExpression aSelectScalarExpression = (SelectScalarExpression)aSelectElement;

                        string identStr = string.Empty;
                        IdentifierOrValueExpression aIdentifierOrValueExpression =
                            aSelectScalarExpression.ColumnName;
                        if (aIdentifierOrValueExpression != null)
                        {
                            if (aIdentifierOrValueExpression.ValueExpression == null)
                            {
                                AddLogText(string.Format("Identifier={0}",
                                                         aIdentifierOrValueExpression.Identifier.Value));
                                identStr = aIdentifierOrValueExpression.Identifier.Value;
                            }
                            else
                            {
                                AddLogText("Expression");
                            }
                        }
                        aColumnInfoList.AddIfNeeded(aSelectElementID, identStr);

                        ScalarExpression aScalarExpression = aSelectScalarExpression.Expression;
                        PrintSelectScalarExperssionRecurse(aSelectElementID, aScalarExpression);
                    }
                    else
                    {
                        aColumnInfoList.AddIfNeeded(aSelectElementID,
                                                    "Error, something else than SelectScalarExpression found");
                        AddLogText("We only support SelectScalarExpression.");
                    }
                    aSelectElementID = aSelectElementID + 1;
                    AddLogText("");
                }
                AddLogText("");
                AddLogText("Table References:");
                FromClause aFromClause = aQuerySpecification.FromClause;
                foreach (TableReference aTableReference in aFromClause.TableReferences)
                {
                    PrintTableReferenceRecurse(aTableReference);
                }
            }
            aColumnInfoList.FillEmptyAlias();
        }//function
Example #24
0
        /// <summary>
        /// Adds attributes to the SELECT clause
        /// </summary>
        /// <param name="query">The SQL query to append to the SELECT clause of</param>
        /// <param name="items">The FetchXML items to process</param>
        /// <param name="prefix">The name or alias of the table being processed</param>
        private static void AddSelectElements(QuerySpecification query, object[] items, string prefix)
        {
            if (items == null)
            {
                return;
            }

            // Handle <all-attributes /> as SELECT table.*
            foreach (var all in items.OfType <allattributes>())
            {
                query.SelectElements.Add(new SelectStarExpression
                {
                    Qualifier = new MultiPartIdentifier
                    {
                        Identifiers =
                        {
                            new Identifier {
                                Value = prefix
                            }
                        }
                    }
                });
            }

            // Handle attributes with each combination of aliases, aggregates, distincts, groupings
            // <attribute name="attr" alias="a" aggregate="count" distinct="true" />
            // <attribute name="attr" alias="a" groupby="true" dategrouping="month" />
            foreach (var attr in items.OfType <FetchAttributeType>())
            {
                var element = new SelectScalarExpression();

                // Core column reference
                var col = new ColumnReferenceExpression
                {
                    MultiPartIdentifier = new MultiPartIdentifier
                    {
                        Identifiers =
                        {
                            new Identifier {
                                Value = prefix
                            },
                            new Identifier {
                                Value = attr.name
                            }
                        }
                    }
                };

                // Apply aggregates or date grouping as function calls
                if (attr.aggregateSpecified)
                {
                    var func = new FunctionCall
                    {
                        FunctionName = new Identifier {
                            Value = attr.aggregate == AggregateType.countcolumn ? "count" : attr.aggregate.ToString()
                        },
                        Parameters =
                        {
                            col
                        }
                    };

                    if (attr.distinctSpecified && attr.distinct == FetchBoolType.@true)
                    {
                        func.UniqueRowFilter = UniqueRowFilter.Distinct;
                    }

                    element.Expression = func;
                }
                else if (attr.dategroupingSpecified)
                {
                    var func = new FunctionCall
                    {
                        FunctionName = new Identifier {
                            Value = "DATEPART"
                        },
                        Parameters =
                        {
                            new ColumnReferenceExpression
                            {
                                MultiPartIdentifier = new MultiPartIdentifier
                                {
                                    Identifiers =
                                    {
                                        new Identifier
                                        {
                                            Value = attr.dategrouping.ToString()
                                        }
                                    }
                                }
                            },
                            col
                        }
                    };

                    element.Expression = func;
                }
                else
                {
                    element.Expression = col;
                }

                // Apply alias
                if (!String.IsNullOrEmpty(attr.alias) && (attr.aggregateSpecified || attr.alias != attr.name))
                {
                    element.ColumnName = new IdentifierOrValueExpression {
                        Identifier = new Identifier {
                            Value = attr.alias
                        }
                    }
                }
                ;

                query.SelectElements.Add(element);

                // Apply grouping
                if (attr.groupbySpecified && attr.groupby == FetchBoolType.@true)
                {
                    if (query.GroupByClause == null)
                    {
                        query.GroupByClause = new GroupByClause();
                    }

                    if (attr.dategroupingSpecified)
                    {
                        query.GroupByClause.GroupingSpecifications.Add(new ExpressionGroupingSpecification
                        {
                            Expression = new FunctionCall
                            {
                                FunctionName = new Identifier {
                                    Value = "DATEPART"
                                },
                                Parameters =
                                {
                                    new ColumnReferenceExpression
                                    {
                                        MultiPartIdentifier = new MultiPartIdentifier
                                        {
                                            Identifiers =
                                            {
                                                new Identifier
                                                {
                                                    Value = attr.dategrouping.ToString()
                                                }
                                            }
                                        }
                                    },
                                    col
                                }
                            }
                        });
                    }
                    else
                    {
                        query.GroupByClause.GroupingSpecifications.Add(new ExpressionGroupingSpecification {
                            Expression = col
                        });
                    }
                }
            }
        }