Skip to content

Commit

Permalink
Merge pull request #561 from mk3008/560-review-argument-order-for-exi…
Browse files Browse the repository at this point in the history
…sts-function

Added ExistsIn and NotExistsIn functions with improved argument order
  • Loading branch information
mk3008 authored Oct 30, 2024
2 parents e3692bb + 2d01e6c commit 2bb205e
Show file tree
Hide file tree
Showing 3 changed files with 240 additions and 14 deletions.
2 changes: 1 addition & 1 deletion src/Carbunql/Carbunql.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<Title></Title>
<Copyright>mk3008net</Copyright>
<Description>Carbunql is an advanced Raw SQL editing library.</Description>
<Version>0.8.13.2</Version>
<Version>0.8.14</Version>
<Authors>mk3008net</Authors>
<PackageProjectUrl>https://github.com/mk3008/Carbunql</PackageProjectUrl>
<PackageReadmeFile>README.md</PackageReadmeFile>
Expand Down
184 changes: 174 additions & 10 deletions src/Carbunql/Fluent/SelectQueryWhereExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -522,7 +522,46 @@ public static SelectQuery Exists(this SelectQuery query, FluentTable validationT
/// <param name="keyColumnNames">A list of key column names used in the query.</param>
/// <param name="validationTable">The FluentTable object used for validation.</param>
/// <returns>Returns the updated SelectQuery object.</returns>
[Obsolete("use ExistsIn")]
public static SelectQuery Exists(this SelectQuery query, IEnumerable<string> keyColumnNames, FluentTable validationTable)
{
return query.ExistsIn(validationTable, keyColumnNames);
}

/// <summary>
/// Applies an Exists query to the specified validation table based on the given table and key column names.
/// </summary>
/// <param name="query">The SelectQuery object to operate on.</param>
/// <param name="table">The FluentTable object to operate on.</param>
/// <param name="keyColumnNames">A list of key column names used in the query.</param>
/// <param name="validationTable">The FluentTable object used for validation.</param>
/// <returns>Returns the updated SelectQuery object.</returns>
[Obsolete("use ExistsIn")]
public static SelectQuery Exists(this SelectQuery query, FluentTable table, IEnumerable<string> keyColumnNames, FluentTable validationTable)
{
return query.ExistsIn(validationTable, keyColumnNames, table);
}

[Obsolete("use ExistsIn")]
public static SelectQuery Exists(this SelectQuery query, IEnumerable<string> keyColumnNames, string validationTableName)
{
return query.ExistsIn(validationTableName, keyColumnNames);
}

[Obsolete("use ExistsIn")]
public static SelectQuery Exists(this SelectQuery query, string tableName, IEnumerable<string> keyColumnNames, string validationTableName)
{
return query.ExistsIn(validationTableName, keyColumnNames, tableName);
}

/// <summary>
/// Applies an Exists query to the specified validation table based on the key column names.
/// </summary>
/// <param name="query">The SelectQuery object to operate on.</param>
/// <param name="validationTable">The FluentTable object used for validation.</param>
/// <param name="keyColumnNames">A list of key column names used in the query.</param>
/// <returns>Returns the updated SelectQuery object.</returns>
public static SelectQuery ExistsIn(this SelectQuery query, FluentTable validationTable, IEnumerable<string> keyColumnNames)
{
if (validationTable.IsCommonTable)
{
Expand All @@ -546,15 +585,58 @@ public static SelectQuery Exists(this SelectQuery query, IEnumerable<string> key
return query;
}

public static SelectQuery ExistsIn(this SelectQuery query, FluentTable validationTable, string condition)
{
if (validationTable.IsCommonTable)
{
query.With(validationTable);
}

query.Where(() =>
{
var sq = new SelectQuery().From(validationTable);
sq.Where(condition);
return sq.ToExists();
});

return query;
}

public static SelectQuery ExistsIn(this SelectQuery query, FluentTable validationTable, IEnumerable<string> validationcolumns, FluentTable table, IEnumerable<string> columns)
{
if (columns.Count() != validationcolumns.Count())
{
throw new ArgumentException("The number of elements in columns and validationcolumns must be the same.");
}

var columnMaps = columns.Zip(validationcolumns, (left, right) => (left, right));

var lquery = new SelectQuery().From(table).GetCurrentQuerySource();
var rquery = new SelectQuery().From(validationTable).GetCurrentQuerySource();

var condition = string.Join(" and ", columnMaps.Select(item => $"{rquery.GetColumn(item.right, isAliasIncluded: true)} = {lquery.GetColumn(item.left, isAliasIncluded: true)}"));

var targetQuery = query.GetQuerySources()
.Where(x => x.HasTable(table.Alias, true))
.EnsureAny($"table:{table.Alias}")
.GetRootsByQuery()
.First()
.Query;

targetQuery.ExistsIn(validationTable, condition);

return query;
}

/// <summary>
/// Applies an Exists query to the specified validation table based on the given table and key column names.
/// </summary>
/// <param name="query">The SelectQuery object to operate on.</param>
/// <param name="table">The FluentTable object to operate on.</param>
/// <param name="keyColumnNames">A list of key column names used in the query.</param>
/// <param name="validationTable">The FluentTable object used for validation.</param>
/// <param name="keyColumnNames">A list of key column names used in the query.</param>
/// <param name="table">The FluentTable object to operate on.</param>
/// <returns>Returns the updated SelectQuery object.</returns>
public static SelectQuery Exists(this SelectQuery query, FluentTable table, IEnumerable<string> keyColumnNames, FluentTable validationTable)
public static SelectQuery ExistsIn(this SelectQuery query, FluentTable validationTable, IEnumerable<string> keyColumnNames, FluentTable table)
{
if (validationTable.IsCommonTable)
{
Expand All @@ -580,13 +662,13 @@ public static SelectQuery Exists(this SelectQuery query, FluentTable table, IEnu
return query;
}

public static SelectQuery Exists(this SelectQuery query, IEnumerable<string> keyColumnNames, string validationTableName)
public static SelectQuery ExistsIn(this SelectQuery query, string validationTableName, IEnumerable<string> keyColumnNames)
{
query.AddExists(keyColumnNames, validationTableName);
return query;
}

public static SelectQuery Exists(this SelectQuery query, string tableName, IEnumerable<string> keyColumnNames, string validationTableName)
public static SelectQuery ExistsIn(this SelectQuery query, string validationTableName, IEnumerable<string> keyColumnNames, string tableName)
{
query.AddExists(tableName, keyColumnNames, validationTableName);
return query;
Expand All @@ -605,7 +687,89 @@ public static SelectQuery NotExists(this SelectQuery query, FluentTable validati
/// <param name="keyColumnNames">A list of key column names used in the query.</param>
/// <param name="validationTable">The FluentTable object used for validation.</param>
/// <returns>Returns the updated SelectQuery object.</returns>
[Obsolete("use NotExistsIn")]
public static SelectQuery NotExists(this SelectQuery query, IEnumerable<string> keyColumnNames, FluentTable validationTable)
{
return query.NotExistsIn(validationTable, keyColumnNames);
}

/// <summary>
/// Applies a NotExists query to the specified validation table based on the given table and key column names.
/// </summary>
/// <param name="query">The SelectQuery object to operate on.</param>
/// <param name="table">The FluentTable object to operate on.</param>
/// <param name="keyColumnNames">A list of key column names used in the query.</param>
/// <param name="validationTable">The FluentTable object used for validation.</param>
/// <returns>Returns the updated SelectQuery object.</returns>
[Obsolete("use NotExistsIn")]
public static SelectQuery NotExists(this SelectQuery query, FluentTable table, IEnumerable<string> keyColumnNames, FluentTable validationTable)
{
return query.NotExistsIn(validationTable, keyColumnNames, table);
}

[Obsolete("use NotExistsIn")]
public static SelectQuery NotExists(this SelectQuery query, IEnumerable<string> keyColumnNames, string validationTableName)
{
return query.NotExistsIn(validationTableName, keyColumnNames);
}

[Obsolete("use NotExistsIn")]
public static SelectQuery NotExists(this SelectQuery query, string tableName, IEnumerable<string> keyColumnNames, string validationTableName)
{
return query.NotExistsIn(validationTableName, keyColumnNames, tableName);
}

public static SelectQuery NotExistsIn(this SelectQuery query, FluentTable validationTable, string condition)
{
if (validationTable.IsCommonTable)
{
query.With(validationTable);
}

query.Where(() =>
{
var sq = new SelectQuery().From(validationTable);
sq.Where(condition);
return sq.ToNotExists();
});

return query;
}

public static SelectQuery NotExistsIn(this SelectQuery query, FluentTable validationTable, IEnumerable<string> validationcolumns, FluentTable table, IEnumerable<string> columns)
{
if (columns.Count() != validationcolumns.Count())
{
throw new ArgumentException("The number of elements in columns and validationcolumns must be the same.");
}

var columnMaps = columns.Zip(validationcolumns, (left, right) => (left, right));

var lquery = new SelectQuery().From(table).GetCurrentQuerySource();
var rquery = new SelectQuery().From(validationTable).GetCurrentQuerySource();

var condition = string.Join(" and ", columnMaps.Select(item => $"{rquery.GetColumn(item.right, isAliasIncluded: true)} = {lquery.GetColumn(item.left, isAliasIncluded: true)}"));

var targetQuery = query.GetQuerySources()
.Where(x => x.HasTable(table.Alias, true))
.EnsureAny($"table:{table.Alias}")
.GetRootsByQuery()
.First()
.Query;

targetQuery.NotExistsIn(validationTable, condition);

return query;
}

/// <summary>
/// Applies a NotExists query to the specified validation table based on the key column names.
/// </summary>
/// <param name="query">The SelectQuery object to operate on.</param>
/// <param name="validationTable">The FluentTable object used for validation.</param>
/// <param name="keyColumnNames">A list of key column names used in the query.</param>
/// <returns>Returns the updated SelectQuery object.</returns>
public static SelectQuery NotExistsIn(this SelectQuery query, FluentTable validationTable, IEnumerable<string> keyColumnNames)
{
if (validationTable.IsCommonTable)
{
Expand Down Expand Up @@ -633,11 +797,11 @@ public static SelectQuery NotExists(this SelectQuery query, IEnumerable<string>
/// Applies a NotExists query to the specified validation table based on the given table and key column names.
/// </summary>
/// <param name="query">The SelectQuery object to operate on.</param>
/// <param name="table">The FluentTable object to operate on.</param>
/// <param name="keyColumnNames">A list of key column names used in the query.</param>
/// <param name="validationTable">The FluentTable object used for validation.</param>
/// <param name="keyColumnNames">A list of key column names used in the query.</param>
/// <param name="table">The FluentTable object to operate on.</param>
/// <returns>Returns the updated SelectQuery object.</returns>
public static SelectQuery NotExists(this SelectQuery query, FluentTable table, IEnumerable<string> keyColumnNames, FluentTable validationTable)
public static SelectQuery NotExistsIn(this SelectQuery query, FluentTable validationTable, IEnumerable<string> keyColumnNames, FluentTable table)
{
if (validationTable.IsCommonTable)
{
Expand All @@ -663,13 +827,13 @@ public static SelectQuery NotExists(this SelectQuery query, FluentTable table, I
return query;
}

public static SelectQuery NotExists(this SelectQuery query, IEnumerable<string> keyColumnNames, string validationTableName)
public static SelectQuery NotExistsIn(this SelectQuery query, string validationTableName, IEnumerable<string> keyColumnNames)
{
query.AddNotExists(keyColumnNames, validationTableName);
return query;
}

public static SelectQuery NotExists(this SelectQuery query, string tableName, IEnumerable<string> keyColumnNames, string validationTableName)
public static SelectQuery NotExistsIn(this SelectQuery query, string validationTableName, IEnumerable<string> keyColumnNames, string tableName)
{
query.AddNotExists(tableName, keyColumnNames, validationTableName);
return query;
Expand Down
68 changes: 65 additions & 3 deletions test/Carbunql.Fluent.Test/Sample.cs
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ table_a AS a
}

[Fact]
public void SingleTable_Join_Custome()
public void SingleTable_Join_Custom()
{
var tableA = FluentTable.Create("table_a", ["id", "value"], "a");
var tableB = FluentTable.Create("table_b", ["id", "table_a_id", "value"], "b");
Expand Down Expand Up @@ -266,7 +266,7 @@ public void SingleTable_Exists()

var sq = new SelectQuery()
.From(tableA)
.Exists(["table_a_id"], tableB);
.ExistsIn(tableB, ["table_a_id"]);

Monitor.Log(sq);

Expand Down Expand Up @@ -297,7 +297,7 @@ public void SingleTable_Exists_Strict()

var sq = new SelectQuery()
.From(tableA)
.Exists(tableA, ["table_a_id"], tableB);
.ExistsIn(tableB, ["table_a_id"], tableA);

Monitor.Log(sq);

Expand All @@ -319,4 +319,66 @@ table_b AS b

Assert.Equal(expect, sq.ToText());
}

[Fact]
public void SingleTable_Exists_Custom()
{
var tableA = FluentTable.Create("table_a", ["id", "value"], "a");
var tableB = FluentTable.Create("table_b", ["table_a_id", "value"], "b");

var sq = new SelectQuery()
.From(tableA)
.ExistsIn(tableB, ["table_a_id"], tableA, ["id"]);

Monitor.Log(sq);

var expect = """
SELECT
*
FROM
table_a AS a
WHERE
EXISTS (
SELECT
*
FROM
table_b AS b
WHERE
b.table_a_id = a.id
)
""";

Assert.Equal(expect, sq.ToText());
}

[Fact]
public void SingleTable_NotExists_Custom()
{
var tableA = FluentTable.Create("table_a", ["id", "value"], "a");
var tableB = FluentTable.Create("table_b", ["table_a_id", "value"], "b");

var sq = new SelectQuery()
.From(tableA)
.NotExistsIn(tableB, ["table_a_id"], tableA, ["id"]);

Monitor.Log(sq);

var expect = """
SELECT
*
FROM
table_a AS a
WHERE
NOT EXISTS (
SELECT
*
FROM
table_b AS b
WHERE
b.table_a_id = a.id
)
""";

Assert.Equal(expect, sq.ToText());
}
}

0 comments on commit 2bb205e

Please sign in to comment.