Skip to content

Commit b06b438

Browse files
authored
Merge pull request #95 from tomasfabian/90-specify-ignorebyinserts-using-the-model-builder
90 specify ignorebyinserts using the model builder
2 parents d265805 + 78bf5f9 commit b06b438

File tree

19 files changed

+524
-28
lines changed

19 files changed

+524
-28
lines changed

Tests/ksqlDB.RestApi.Client.IntegrationTests/KSql/Linq/JoinsTests.cs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ public static async Task ClassInitialize()
3434

3535
moviesProvider = new MoviesProvider(RestApiProvider);
3636

37+
await ClassCleanup();
38+
3739
var response = await RestApiProvider.CreateStreamAsync<Order>(OrderEntityCreationMetadata, ifNotExists: true);
3840

3941
await moviesProvider.DropTablesAsync();
@@ -93,7 +95,7 @@ public async Task Join()
9395
public async Task LeftJoin()
9496
{
9597
//Arrange
96-
int expectedItemsCount = 2;
98+
int expectedItemsCount = 1;
9799

98100
var source = Context.CreatePushQuery<Movie>(MoviesTableName)
99101
.LeftJoin(
@@ -120,9 +122,9 @@ public async Task LeftJoin()
120122
Assert.AreEqual(MoviesProvider.Movie1.Title, actualValues[0].Title);
121123
Assert.AreEqual(MoviesProvider.LeadActor1.Title, actualValues[0].Title);
122124

123-
actualValues[1].Substr.Length.Should().Be(4);
124-
actualValues[1].Release_Year.Should().BeOneOf(MoviesProvider.Movie1.Release_Year, MoviesProvider.Movie2.Release_Year);
125-
actualValues[1].ActorTitle.Should().BeOneOf(null, MoviesProvider.Movie1.Title, MoviesProvider.Movie2.Title);
125+
actualValues[0].Substr.Length.Should().Be(4);
126+
actualValues[0].Release_Year.Should().BeOneOf(MoviesProvider.Movie1.Release_Year, MoviesProvider.Movie2.Release_Year);
127+
actualValues[0].ActorTitle.Should().BeOneOf(null, MoviesProvider.Movie1.Title, MoviesProvider.Movie2.Title);
126128
}
127129

128130
public record Movie2 : Record

Tests/ksqlDB.RestApi.Client.IntegrationTests/KSql/Linq/ModelBuilderTests.cs

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ public record Tweet : Record
4242
Message = "Hello world",
4343
IsRobot = true,
4444
Amount = 0.00042,
45+
RowTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds()
4546
};
4647

4748
public static readonly Tweet Tweet2 = new()
@@ -50,6 +51,7 @@ public record Tweet : Record
5051
Message = "Wall-e",
5152
IsRobot = false,
5253
Amount = 1,
54+
RowTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds()
5355
};
5456

5557
protected static async Task InitializeDatabase()
@@ -68,6 +70,8 @@ protected static async Task InitializeDatabase()
6870
};
6971
kSqlDbRestApiClient = new KSqlDbRestApiClient(new HttpClientFactory(httpClient), modelBuilder);
7072

73+
await ClassCleanup();
74+
7175
var entityCreationMetadata = new EntityCreationMetadata(TopicName, 1)
7276
{
7377
EntityName = StreamName,
@@ -100,7 +104,7 @@ public static async Task ClassCleanup()
100104
UseIfExistsClause = true,
101105
DeleteTopic = true,
102106
};
103-
await kSqlDbRestApiClient.DropStreamAsync<Models.Tweet>(dropFromItemProperties);
107+
await kSqlDbRestApiClient.DropStreamAsync<Tweet>(dropFromItemProperties);
104108
}
105109

106110
[SetUp]
@@ -123,17 +127,40 @@ public async Task Select()
123127
var source = QuerySource
124128
.ToAsyncEnumerable();
125129

130+
var tweet1 = Tweet1 with { RowTime = 0 };
131+
var tweet2 = Tweet2 with { RowTime = 0 };
132+
126133
//Act
127134
var actualValues = await CollectActualValues(source, expectedItemsCount);
128135

129136
//Assert
130137
var expectedValues = new List<Tweet>
131138
{
132-
Tweet1, Tweet2
139+
tweet1, tweet2
133140
};
134141

135142
expectedItemsCount.Should().Be(actualValues.Count);
136143
CollectionAssert.AreEqual(expectedValues, actualValues);
137144
}
145+
146+
[Test]
147+
public async Task SelectPseudoColumns()
148+
{
149+
//Arrange
150+
int expectedItemsCount = 2;
151+
152+
var source = QuerySource
153+
.Select(c => new{ c.RowTime, c.RowOffset, c.Message })
154+
.ToAsyncEnumerable();
155+
156+
//Act
157+
var actualValues = await CollectActualValues(source, expectedItemsCount);
158+
159+
//Assert
160+
expectedItemsCount.Should().Be(actualValues.Count);
161+
actualValues[0].RowTime.Should().Be(Tweet1.RowTime);
162+
actualValues[0].RowTime.Should().BeGreaterOrEqualTo(0);
163+
actualValues[0].Message.Should().Be(Tweet1.Message);
164+
}
138165
}
139166
}

Tests/ksqlDB.RestApi.Client.IntegrationTests/KSql/Linq/MoviesProvider.cs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,26 +55,30 @@ actor_name VARCHAR
5555
{
5656
Id = 1,
5757
Release_Year = 1986,
58-
Title = "Aliens"
58+
Title = "Aliens",
59+
RowTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds()
5960
};
6061

6162
public static readonly Movie Movie2 = new()
6263
{
6364
Id = 2,
6465
Release_Year = 1988,
65-
Title = "Die Hard"
66+
Title = "Die Hard",
67+
RowTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds()
6668
};
6769

6870
public static readonly Lead_Actor LeadActor1 = new()
6971
{
7072
Actor_Name = "Sigourney Weaver",
71-
Title = "Aliens"
73+
Title = "Aliens",
74+
RowTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds()
7275
};
7376

7477
public static readonly Lead_Actor LeadActor2 = new()
7578
{
7679
Actor_Name = "Al Pacino",
77-
Title = "The Godfather"
80+
Title = "The Godfather",
81+
RowTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds()
7882
};
7983

8084
public async Task<bool> InsertMovieAsync(Movie movie)

Tests/ksqlDB.RestApi.Client.IntegrationTests/Models/Record.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@ namespace ksqlDb.RestApi.Client.IntegrationTests.Models;
44

55
public record Record
66
{
7-
[ksqlDB.RestApi.Client.KSql.RestApi.Statements.Annotations.Ignore]
87
[PseudoColumn]
8+
[IgnoreInDDL]
99
public long RowTime { get; set; }
10+
11+
[ksqlDB.RestApi.Client.KSql.RestApi.Statements.Annotations.Ignore]
12+
[PseudoColumn]
13+
public long? RowOffset { get; set; }
1014
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
using FluentAssertions;
2+
using ksqlDb.RestApi.Client.FluentAPI.Builders;
3+
using ksqlDb.RestApi.Client.Metadata;
4+
using ksqlDb.RestApi.Client.Tests.Models;
5+
using NUnit.Framework;
6+
7+
namespace ksqlDb.RestApi.Client.Tests.FluentAPI.Builders
8+
{
9+
public class EntityTypeBuilderTests
10+
{
11+
private EntityTypeBuilder<Tweet> builder = null!;
12+
13+
[SetUp]
14+
public void TestInitialize()
15+
{
16+
builder = new();
17+
}
18+
19+
[Test]
20+
public void HasKey()
21+
{
22+
//Arrange
23+
24+
//Act
25+
var entityTypeBuilder = builder.HasKey(c => c.Id);
26+
27+
//Assert
28+
entityTypeBuilder.Should().NotBeNull();
29+
((EntityTypeBuilder)entityTypeBuilder).Metadata.PrimaryKeyMemberInfo.Should().NotBeNull();
30+
}
31+
32+
[Test]
33+
public void Property()
34+
{
35+
//Arrange
36+
37+
//Act
38+
var fieldTypeBuilder = builder.Property(c => c.Id);
39+
40+
//Assert
41+
fieldTypeBuilder.Should().NotBeNull();
42+
builder.Metadata.FieldsMetadata.Count().Should().Be(2);
43+
}
44+
45+
[Test]
46+
public void RowTime_Property_ShouldBeIgnoredInDDL()
47+
{
48+
//Arrange
49+
50+
//Act
51+
var fieldTypeBuilder = builder.Property(c => c.Id);
52+
53+
//Assert
54+
fieldTypeBuilder.Should().NotBeNull();
55+
builder.Metadata.FieldsMetadata.First(c => c.MemberInfo.Name == nameof(Tweet.RowTime)).IgnoreInDDL.Should().BeTrue();
56+
}
57+
58+
public class Foo
59+
{
60+
public long RowTime;
61+
}
62+
63+
[Test]
64+
public void RowTime_Field_ShouldBeIgnoredInDDL()
65+
{
66+
//Arrange
67+
68+
//Act
69+
EntityTypeBuilder<Foo> fooBuilder = new();
70+
71+
//Assert
72+
fooBuilder.Metadata.FieldsMetadata.First(c => c.MemberInfo.Name == nameof(Foo.RowTime)).IgnoreInDDL.Should().BeTrue();
73+
}
74+
75+
[Test]
76+
public void DecimalType_ShouldHaveDecimalFieldMetadata()
77+
{
78+
//Arrange
79+
80+
//Act
81+
var fieldTypeBuilder = builder.Property(c => c.AccountBalance);
82+
83+
//Assert
84+
fieldTypeBuilder.Should().NotBeNull();
85+
builder.Metadata.FieldsMetadata
86+
.OfType<DecimalFieldMetadata>()
87+
.First(c => c.MemberInfo.Name == nameof(Tweet.AccountBalance))
88+
.Should().NotBeNull();
89+
}
90+
}
91+
}

Tests/ksqlDB.RestApi.Client.Tests/FluentAPI/Builders/ModelBuilderTests.cs

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,43 @@ public void Property_IgnoreInDML()
8484
entityMetadata!.FieldsMetadata.First(c => c.MemberInfo.Name == nameof(Payment.Description)).IgnoreInDML.Should().BeTrue();
8585
}
8686

87+
[Test]
88+
public void Property_IgnoreInDDL()
89+
{
90+
//Arrange
91+
92+
//Act
93+
var fieldTypeBuilder = builder.Entity<Payment>()
94+
.Property(b => b.Description)
95+
.IgnoreInDDL();
96+
97+
//Assert
98+
fieldTypeBuilder.Should().NotBeNull();
99+
var entityMetadata = ((IMetadataProvider)builder).GetEntities().FirstOrDefault(c => c.Type == typeof(Payment));
100+
entityMetadata.Should().NotBeNull();
101+
entityMetadata!.FieldsMetadata.First(c => c.MemberInfo.Name == nameof(Payment.Description)).IgnoreInDDL.Should().BeTrue();
102+
}
103+
104+
public class RecordExt : ksqlDB.RestApi.Client.KSql.Query.Record
105+
{
106+
public string Title { get; set; }
107+
}
108+
109+
[Test]
110+
public void RowTime_PropertyConvention_IgnoreInDDL()
111+
{
112+
//Arrange
113+
114+
//Act
115+
var fieldTypeBuilder = builder.Entity<RecordExt>();
116+
117+
//Assert
118+
fieldTypeBuilder.Should().NotBeNull();
119+
var entityMetadata = ((IMetadataProvider)builder).GetEntities().FirstOrDefault(c => c.Type == typeof(RecordExt));
120+
entityMetadata.Should().NotBeNull();
121+
entityMetadata!.FieldsMetadata.First(c => c.MemberInfo.Name == nameof(RecordExt.RowTime)).IgnoreInDDL.Should().BeTrue();
122+
}
123+
87124
[Test]
88125
public void Property_HasColumnName()
89126
{
@@ -124,6 +161,56 @@ public void MultiplePropertiesForSameType()
124161
entityMetadata.FieldsMetadata.First(c => c.MemberInfo.Name == nameof(Payment.Amount)).Ignore.Should().BeTrue();
125162
}
126163

164+
[Test]
165+
public void MultipleMappingsForSameProperty()
166+
{
167+
//Arrange
168+
string columnName = "alter";
169+
170+
//Act
171+
var fieldTypeBuilder = builder.Entity<Payment>()
172+
.Property(b => b.Description)
173+
.HasColumnName(columnName);
174+
175+
builder.Entity<Payment>()
176+
.Property(b => b.Description)
177+
.IgnoreInDML();
178+
179+
//Assert
180+
fieldTypeBuilder.Should().NotBeNull();
181+
var entityMetadata = ((IMetadataProvider)builder).GetEntities().FirstOrDefault(c => c.Type == typeof(Payment));
182+
entityMetadata.Should().NotBeNull();
183+
var fieldMetadata = entityMetadata!.FieldsMetadata.First(c => c.MemberInfo.Name == nameof(Payment.Description));
184+
fieldMetadata.ColumnName.Should().Be(columnName);
185+
fieldMetadata.IgnoreInDML.Should().BeTrue();
186+
}
187+
188+
189+
[Test]
190+
public void MultipleMappingsForSameProperty_Decimal()
191+
{
192+
//Arrange
193+
string columnName = "alter";
194+
short precision = 2;
195+
short scale = 3;
196+
197+
//Act
198+
builder.Entity<Payment>()
199+
.Property(b => b.Amount)
200+
.Decimal(precision, scale);
201+
202+
builder.Entity<Payment>()
203+
.Property(b => b.Amount)
204+
.HasColumnName(columnName);
205+
206+
//Assert
207+
var entityMetadata = ((IMetadataProvider)builder).GetEntities().FirstOrDefault(c => c.Type == typeof(Payment));
208+
entityMetadata.Should().NotBeNull();
209+
var fieldMetadata = entityMetadata!.FieldsMetadata.First(c => c.MemberInfo.Name == nameof(Payment.Amount));
210+
fieldMetadata.ColumnName.Should().Be(columnName);
211+
((DecimalFieldMetadata)fieldMetadata).Precision.Should().Be(precision);
212+
}
213+
127214
[Test]
128215
public void Property_IgnoreNestedField()
129216
{

0 commit comments

Comments
 (0)