Skip to content

Implement column-as keyword for 'select' with SelectAs(). #499

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
158 changes: 155 additions & 3 deletions QueryBuilder.Tests/AggregateTests.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,70 @@
using SqlKata.Compilers;
using SqlKata.Tests.Infrastructure;
using System;
using Xunit;

namespace SqlKata.Tests
{
public class AggregateTests : TestSupport
{
[Fact]
public void AsAggregateEmpty()
{
Assert.Throws<ArgumentException>(() => new Query("A").AsAggregate("aggregate", new string[] { }));
}

[Fact]
public void AsAggregate()
{
var query = new Query("A").AsAggregate("aggregate", new[] { "Column" });

var c = Compile(query);

Assert.Equal("SELECT AGGREGATE([Column]) AS [aggregate] FROM [A]", c[EngineCodes.SqlServer]);
Assert.Equal("SELECT AGGREGATE(`Column`) AS `aggregate` FROM `A`", c[EngineCodes.MySql]);
Assert.Equal("SELECT AGGREGATE(\"Column\") AS \"aggregate\" FROM \"A\"", c[EngineCodes.PostgreSql]);
Assert.Equal("SELECT AGGREGATE(\"COLUMN\") AS \"AGGREGATE\" FROM \"A\"", c[EngineCodes.Firebird]);
}

[Fact]
public void AsAggregateAlias()
{
var query = new Query("A").AsAggregate("aggregate", new[] { "Column" }, "Alias");

var c = Compile(query);

Assert.Equal("SELECT AGGREGATE([Column]) AS [Alias] FROM [A]", c[EngineCodes.SqlServer]);
Assert.Equal("SELECT AGGREGATE(`Column`) AS `Alias` FROM `A`", c[EngineCodes.MySql]);
Assert.Equal("SELECT AGGREGATE(\"Column\") AS \"Alias\" FROM \"A\"", c[EngineCodes.PostgreSql]);
Assert.Equal("SELECT AGGREGATE(\"COLUMN\") AS \"ALIAS\" FROM \"A\"", c[EngineCodes.Firebird]);
}

[Fact]
public void AsAggregateMultipleColumns()
{
var query = new Query("A").AsAggregate("aggregate", new[] { "Column1", "Column2" });

var c = Compile(query);

Assert.Equal("SELECT AGGREGATE(*) AS [aggregate] FROM (SELECT 1 FROM [A] WHERE [Column1] IS NOT NULL AND [Column2] IS NOT NULL) AS [AggregateQuery]", c[EngineCodes.SqlServer]);
Assert.Equal("SELECT AGGREGATE(*) AS `aggregate` FROM (SELECT 1 FROM `A` WHERE `Column1` IS NOT NULL AND `Column2` IS NOT NULL) AS `AggregateQuery`", c[EngineCodes.MySql]);
Assert.Equal("SELECT AGGREGATE(*) AS \"AGGREGATE\" FROM (SELECT 1 FROM \"A\" WHERE \"COLUMN1\" IS NOT NULL AND \"COLUMN2\" IS NOT NULL) AS \"AGGREGATEQUERY\"", c[EngineCodes.Firebird]);
Assert.Equal("SELECT AGGREGATE(*) AS \"aggregate\" FROM (SELECT 1 FROM \"A\" WHERE \"Column1\" IS NOT NULL AND \"Column2\" IS NOT NULL) AS \"AggregateQuery\"", c[EngineCodes.PostgreSql]);
}

[Fact]
public void AsAggregateMultipleColumnsAlias()
{
var query = new Query("A").AsAggregate("aggregate", new[] { "Column1", "Column2" }, "Alias");

var c = Compile(query);

Assert.Equal("SELECT AGGREGATE(*) AS [Alias] FROM (SELECT 1 FROM [A] WHERE [Column1] IS NOT NULL AND [Column2] IS NOT NULL) AS [AliasAggregateQuery]", c[EngineCodes.SqlServer]);
Assert.Equal("SELECT AGGREGATE(*) AS `Alias` FROM (SELECT 1 FROM `A` WHERE `Column1` IS NOT NULL AND `Column2` IS NOT NULL) AS `AliasAggregateQuery`", c[EngineCodes.MySql]);
Assert.Equal("SELECT AGGREGATE(*) AS \"ALIAS\" FROM (SELECT 1 FROM \"A\" WHERE \"COLUMN1\" IS NOT NULL AND \"COLUMN2\" IS NOT NULL) AS \"ALIASAGGREGATEQUERY\"", c[EngineCodes.Firebird]);
Assert.Equal("SELECT AGGREGATE(*) AS \"Alias\" FROM (SELECT 1 FROM \"A\" WHERE \"Column1\" IS NOT NULL AND \"Column2\" IS NOT NULL) AS \"AliasAggregateQuery\"", c[EngineCodes.PostgreSql]);
}

[Fact]
public void Count()
{
Expand All @@ -19,14 +78,67 @@ public void Count()
Assert.Equal("SELECT COUNT(*) AS \"COUNT\" FROM \"A\"", c[EngineCodes.Firebird]);
}

[Fact]
public void CountAsStarAlias()
{
var query = new Query("A").AsCountAs("*", "Alias");

var c = Compile(query);

Assert.Equal("SELECT COUNT(*) AS [Alias] FROM [A]", c[EngineCodes.SqlServer]);
Assert.Equal("SELECT COUNT(*) AS `Alias` FROM `A`", c[EngineCodes.MySql]);
Assert.Equal("SELECT COUNT(*) AS \"Alias\" FROM \"A\"", c[EngineCodes.PostgreSql]);
Assert.Equal("SELECT COUNT(*) AS \"ALIAS\" FROM \"A\"", c[EngineCodes.Firebird]);
}

[Fact]
public void CountAsColumnAlias()
{
var query = new Query("A").AsCountAs("Column", "Alias");

var c = Compile(query);

Assert.Equal("SELECT COUNT([Column]) AS [Alias] FROM [A]", c[EngineCodes.SqlServer]);
Assert.Equal("SELECT COUNT(`Column`) AS `Alias` FROM `A`", c[EngineCodes.MySql]);
Assert.Equal("SELECT COUNT(\"Column\") AS \"Alias\" FROM \"A\"", c[EngineCodes.PostgreSql]);
Assert.Equal("SELECT COUNT(\"COLUMN\") AS \"ALIAS\" FROM \"A\"", c[EngineCodes.Firebird]);
}

[Fact]
public void CountDoesntModifyColumns()
{
{
var columns = new string[] { };
var query = new Query("A").AsCount(columns);
Compile(query);
Assert.Equal(columns, new string[] { });
}
{
var columns = new[] { "ColumnA", "ColumnB" };
var query = new Query("A").AsCount(columns);
Compile(query);
Assert.Equal(columns, new[] { "ColumnA", "ColumnB" });
}
}

[Fact]
public void CountMultipleColumns()
{
var query = new Query("A").AsCount(new[] { "ColumnA", "ColumnB" });

var c = Compile(query);

Assert.Equal("SELECT COUNT(*) AS [count] FROM (SELECT 1 FROM [A] WHERE [ColumnA] IS NOT NULL AND [ColumnB] IS NOT NULL) AS [countQuery]", c[EngineCodes.SqlServer]);
Assert.Equal("SELECT COUNT(*) AS [count] FROM (SELECT 1 FROM [A] WHERE [ColumnA] IS NOT NULL AND [ColumnB] IS NOT NULL) AS [CountQuery]", c[EngineCodes.SqlServer]);
}

[Fact]
public void CountAsMultipleColumns()
{
var query = new Query("A").AsCountAs(new[] { "ColumnA", "ColumnB" }, "Alias");

var c = Compile(query);

Assert.Equal("SELECT COUNT(*) AS [Alias] FROM (SELECT 1 FROM [A] WHERE [ColumnA] IS NOT NULL AND [ColumnB] IS NOT NULL) AS [AliasCountQuery]", c[EngineCodes.SqlServer]);
}

[Fact]
Expand All @@ -36,7 +148,7 @@ public void DistinctCount()

var c = Compile(query);

Assert.Equal("SELECT COUNT(*) AS [count] FROM (SELECT DISTINCT * FROM [A]) AS [countQuery]", c[EngineCodes.SqlServer]);
Assert.Equal("SELECT COUNT(*) AS [count] FROM (SELECT DISTINCT * FROM [A]) AS [CountQuery]", c[EngineCodes.SqlServer]);
}

[Fact]
Expand All @@ -46,7 +158,7 @@ public void DistinctCountMultipleColumns()

var c = Compile(query);

Assert.Equal("SELECT COUNT(*) AS [count] FROM (SELECT DISTINCT [ColumnA], [ColumnB] FROM [A]) AS [countQuery]", c[EngineCodes.SqlServer]);
Assert.Equal("SELECT COUNT(*) AS [count] FROM (SELECT DISTINCT [ColumnA], [ColumnB] FROM [A]) AS [CountQuery]", c[EngineCodes.SqlServer]);
}

[Fact]
Expand All @@ -59,6 +171,16 @@ public void Average()
Assert.Equal("SELECT AVG([TTL]) AS [avg] FROM [A]", c[EngineCodes.SqlServer]);
}

[Fact]
public void AverageAlias()
{
var query = new Query("A").AsAverageAs("TTL", "Alias");

var c = Compile(query);

Assert.Equal("SELECT AVG([TTL]) AS [Alias] FROM [A]", c[EngineCodes.SqlServer]);
}

[Fact]
public void Sum()
{
Expand All @@ -69,6 +191,16 @@ public void Sum()
Assert.Equal("SELECT SUM([PacketsDropped]) AS [sum] FROM [A]", c[EngineCodes.SqlServer]);
}

[Fact]
public void SumAlias()
{
var query = new Query("A").AsSumAs("PacketsDropped", "Alias");

var c = Compile(query);

Assert.Equal("SELECT SUM([PacketsDropped]) AS [Alias] FROM [A]", c[EngineCodes.SqlServer]);
}

[Fact]
public void Max()
{
Expand All @@ -79,6 +211,16 @@ public void Max()
Assert.Equal("SELECT MAX([LatencyMs]) AS [max] FROM [A]", c[EngineCodes.SqlServer]);
}

[Fact]
public void MaxAlias()
{
var query = new Query("A").AsMaxAs("LatencyMs", "Alias");

var c = Compile(query);

Assert.Equal("SELECT MAX([LatencyMs]) AS [Alias] FROM [A]", c[EngineCodes.SqlServer]);
}

[Fact]
public void Min()
{
Expand All @@ -88,5 +230,15 @@ public void Min()

Assert.Equal("SELECT MIN([LatencyMs]) AS [min] FROM [A]", c[EngineCodes.SqlServer]);
}

[Fact]
public void MinAlias()
{
var query = new Query("A").AsMinAs("LatencyMs", "Alias");

var c = Compile(query);

Assert.Equal("SELECT MIN([LatencyMs]) AS [Alias] FROM [A]", c[EngineCodes.SqlServer]);
}
}
}
54 changes: 54 additions & 0 deletions QueryBuilder.Tests/SelectTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,45 @@ public void BasicSelectEnumerable()
Assert.Equal("SELECT \"id\", \"name\" FROM \"users\"", c[EngineCodes.Oracle]);
}

[Fact]
public void SelectAsOneColumn()
{
var query = new Query().SelectAs("Row", "Alias").From("Table");

var c = Compile(query);
Assert.Equal("SELECT [Row] AS [Alias] FROM [Table]", c[EngineCodes.SqlServer]);
Assert.Equal("SELECT `Row` AS `Alias` FROM `Table`", c[EngineCodes.MySql]);
Assert.Equal("SELECT \"Row\" AS \"Alias\" FROM \"Table\"", c[EngineCodes.PostgreSql]);
Assert.Equal("SELECT \"ROW\" AS \"ALIAS\" FROM \"TABLE\"", c[EngineCodes.Firebird]);
Assert.Equal("SELECT \"Row\" \"Alias\" FROM \"Table\"", c[EngineCodes.Oracle]);
}

[Fact]
public void SelectAsSingletonList()
{
var query = new Query().SelectAs(("Row", "Alias")).From("Table");

var c = Compile(query);
Assert.Equal("SELECT [Row] AS [Alias] FROM [Table]", c[EngineCodes.SqlServer]);
Assert.Equal("SELECT `Row` AS `Alias` FROM `Table`", c[EngineCodes.MySql]);
Assert.Equal("SELECT \"Row\" AS \"Alias\" FROM \"Table\"", c[EngineCodes.PostgreSql]);
Assert.Equal("SELECT \"ROW\" AS \"ALIAS\" FROM \"TABLE\"", c[EngineCodes.Firebird]);
Assert.Equal("SELECT \"Row\" \"Alias\" FROM \"Table\"", c[EngineCodes.Oracle]);
}

[Fact]
public void SelectAsMultipleColumns()
{
var query = new Query().SelectAs(("Row1", "Alias1"), ("Row2", "Alias2")).From("Table");

var c = Compile(query);
Assert.Equal("SELECT [Row1] AS [Alias1], [Row2] AS [Alias2] FROM [Table]", c[EngineCodes.SqlServer]);
Assert.Equal("SELECT `Row1` AS `Alias1`, `Row2` AS `Alias2` FROM `Table`", c[EngineCodes.MySql]);
Assert.Equal("SELECT \"Row1\" AS \"Alias1\", \"Row2\" AS \"Alias2\" FROM \"Table\"", c[EngineCodes.PostgreSql]);
Assert.Equal("SELECT \"ROW1\" AS \"ALIAS1\", \"ROW2\" AS \"ALIAS2\" FROM \"TABLE\"", c[EngineCodes.Firebird]);
Assert.Equal("SELECT \"Row1\" \"Alias1\", \"Row2\" \"Alias2\" FROM \"Table\"", c[EngineCodes.Oracle]);
}

[Fact]
public void BasicSelectWhereBindingIsEmptyOrNull()
{
Expand Down Expand Up @@ -74,6 +113,21 @@ public void ExpandedSelect()
Assert.Equal("SELECT `users`.`id`, `users`.`name`, `users`.`age` FROM `users`", c[EngineCodes.MySql]);
}

[Fact]
public void ExpandedSelectAs()
{
var q = new Query().From("users").SelectAs(("users.{id,name, age}", "Alias"));
var c = Compile(q);

// This result is weird (but valid syntax), and at least it works in
// a somewhat explainable way, as opposed to regular Select() when
// combining the expanded syntax and the 'as' SQLKata keyword support
// which simply silently stops working when the {...} expansion is
// applied.
Assert.Equal("SELECT [users].[id] AS [Alias], [users].[name] AS [Alias], [users].[age] AS [Alias] FROM [users]", c[EngineCodes.SqlServer]);
Assert.Equal("SELECT `users`.`id` AS `Alias`, `users`.`name` AS `Alias`, `users`.`age` AS `Alias` FROM `users`", c[EngineCodes.MySql]);
}

[Fact]
public void ExpandedSelectWithSchema()
{
Expand Down
6 changes: 6 additions & 0 deletions QueryBuilder/Clauses/AggregateClause.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ public class AggregateClause : AbstractClause
/// </value>
public List<string> Columns { get; set; }

/// <summary>
/// Gets or sets the alias of the result column.
/// </summary>
public string Alias { get; set; }

/// <summary>
/// Gets or sets the type of aggregate function.
/// </summary>
Expand All @@ -32,6 +37,7 @@ public override AbstractClause Clone()
Engine = Engine,
Type = Type,
Columns = new List<string>(Columns),
Alias = Alias,
Component = Component,
};
}
Expand Down
6 changes: 6 additions & 0 deletions QueryBuilder/Clauses/ColumnClause.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
using System.Diagnostics;

namespace SqlKata
{
public abstract class AbstractColumn : AbstractClause
{
public string Alias { get; set; }
}

/// <summary>
Expand All @@ -26,6 +29,7 @@ public override AbstractClause Clone()
Engine = Engine,
Name = Name,
Component = Component,
Alias = Alias,
};
}
}
Expand All @@ -50,6 +54,7 @@ public override AbstractClause Clone()
Engine = Engine,
Query = Query.Clone(),
Component = Component,
Alias = Alias,
};
}
}
Expand All @@ -68,6 +73,7 @@ public class RawColumn : AbstractColumn
/// <inheritdoc />
public override AbstractClause Clone()
{
Debug.Assert(string.IsNullOrEmpty(Alias), "Raw columns cannot have an alias");
return new RawColumn
{
Engine = Engine,
Expand Down
Loading