Skip to content

Commit

Permalink
feat(command): allow join of tables on itself
Browse files Browse the repository at this point in the history
  • Loading branch information
JonasSchubert committed Mar 1, 2024
1 parent 7f1e3b6 commit d53d6f9
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 3 deletions.
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,35 @@ public class ExamplesRepository : IExamplesRepository
}
```

You can also join a table on itself:

```c#
using System;
using Snowflake.Data.Xt;

namespace SnowflakeApplication;

[SnowflakeTable(
name: "COST_CENTER",
alias: "costCenter1")]
[SnowflakeJoin(
table: "COST_CENTER",
alias: "costCenter2",
type: SnowflakeJoinAttribute.Left,
condition: "costCenter1.COST_CENTER_ID = costCenter2.COST_CENTER_ID")]
public class Example
{
[SnowflakeColumn(name: "VALUE")]
public decimal Value { get; set; }

[SnowflakeColumn(name: "ADDRESS", table: "COST_CENTER")]
public string Address { get; set; }

[SnowflakeColumn(name: "IS_READY", table: "COST_CENTER", alias: "costCenter2")] // Alias must be provided
public bool IsReady { get; set; }
}
```

You can also reuse a snowflake database connection:

```c#
Expand Down
9 changes: 8 additions & 1 deletion src/Attributes/SnowflakeColumnAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,19 @@ public sealed class SnowflakeColumnAttribute : Attribute
/// </summary>
/// <param name="name">The name.</param>
/// <param name="table">The table.</param>
public SnowflakeColumnAttribute(string? name = default, string? table = default)
/// <param name="alias">The alias.</param>
public SnowflakeColumnAttribute(string? name = default, string? table = default, string? alias = default)
{
this.Alias = alias;
this.Name = name ?? string.Empty;
this.Table = table;
}

/// <summary>
/// Gets the alias.
/// </summary>
public string? Alias { get; internal set; }

/// <summary>
/// Gets the name.
/// </summary>
Expand Down
5 changes: 3 additions & 2 deletions src/Command/SnowflakeCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -184,8 +184,9 @@ protected string Columns
{
var column = property.Value;
var table = column.Table ?? this.Table.Name;
var tableAlias = string.Equals(this.Table.Name, table, StringComparison.Ordinal) ? this.Table.Alias ?? string.Empty
: this.Joins.SingleOrDefault(join => string.Equals(join.Table, table, StringComparison.Ordinal))?.Alias ?? string.Empty;
var tableAlias = column.Alias ?? (string.Equals(this.Table.Name, table, StringComparison.Ordinal)
? this.Table.Alias ?? string.Empty
: this.Joins.SingleOrDefault(join => string.Equals(join.Table, table, StringComparison.Ordinal))?.Alias ?? string.Empty);

columns.Append($"{tableAlias}{(string.IsNullOrWhiteSpace(tableAlias) ? string.Empty : ".")}{column.Name}, ");
}
Expand Down
13 changes: 13 additions & 0 deletions tests/Command/SnowflakeCommand.Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,17 @@ public void Constructor_ShouldFill_SELECT_FROM_JOIN_ForClassWithJoin()
// Assert
sql.Should().Be("SELECT bar.ID, foo.PROP_1, bar.Prop_2 FROM DATABASE.SCHEMA.BAR AS bar LEFT JOIN DATABASE.SCHEMA.FOO AS foo ON bar.ID = foo.ID");
}

[Fact]
public void Constructor_ShouldFill_SELECT_FROM_JOIN_ForClassWithJoinOnItself()
{
// Arrange
var command = new SnowflakeCommand<SnowflakeClass3>("DATABASE", "SCHEMA");

// Act
var sql = command.Sql;

// Assert
sql.Should().Be("SELECT bar1.ID, bar1.PROP_1, bar2.Prop_2 FROM DATABASE.SCHEMA.BAR AS bar1 LEFT JOIN DATABASE.SCHEMA.BAR AS bar2 ON bar1.ID = bar2.ID");
}
}
20 changes: 20 additions & 0 deletions tests/TestClasses.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,23 @@ internal sealed class SnowflakeClass2
[SnowflakeColumn]
public string? Prop_2 { get; set; }
}

[SnowflakeTable(
name: "BAR",
alias: "bar1")]
[SnowflakeJoin(
table: "BAR",
alias: "bar2",
type: SnowflakeJoinAttribute.Left,
condition: "bar1.ID = bar2.ID")]
internal sealed class SnowflakeClass3
{
[SnowflakeColumn("ID")]
public int Id { get; set; }

[SnowflakeColumn("PROP_1", "BAR")]
public string? Property1 { get; set; }

[SnowflakeColumn("Prop_2", "BAR", "bar2")]
public string? Prop_2 { get; set; }
}

0 comments on commit d53d6f9

Please sign in to comment.