-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
4972cb8
commit baec815
Showing
6 changed files
with
234 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
using Apache.Arrow; | ||
using Apache.Arrow.Memory; | ||
using DeltaLake.Table; | ||
|
||
namespace DeltaLake.Tests.Table; | ||
public class MergeTests | ||
{ | ||
[Fact] | ||
public async Task Merge_Memory_Full_Test() | ||
{ | ||
var query = @"MERGE INTO mytable USING newdata | ||
ON newdata.test = mytable.test | ||
WHEN MATCHED THEN | ||
UPDATE SET | ||
second = newdata.second, | ||
third = newdata.third | ||
WHEN NOT MATCHED BY SOURCE THEN DELETE | ||
WHEN NOT MATCHED BY TARGET | ||
THEN INSERT ( | ||
test, | ||
second, | ||
third | ||
) | ||
VALUES ( | ||
newdata.test, | ||
'inserted data', | ||
99 | ||
)"; | ||
await BaseMergeTest(query, batches => | ||
{ | ||
var column1 = batches.SelectMany(batch => ((Int32Array)batch.Column(0)).Values.ToArray()).OrderBy(i => i).ToArray(); | ||
Assert.True(column1.SequenceEqual([5, 6, 7, 8, 9, 10, 11, 12, 13, 14])); | ||
var column2 = batches.SelectMany(batch => ((IReadOnlyList<string>)(StringArray)batch.Column(1)).ToArray()).OrderBy(i => i).ToArray(); | ||
Assert.True(column2.SequenceEqual(["hello", "hello", "hello", "hello", "hello", "inserted data", "inserted data", "inserted data", "inserted data", "inserted data"])); | ||
var column3 = batches.SelectMany(batch => ((Int64Array)batch.Column(2)).Values.ToArray()).OrderBy(i => i).ToArray(); | ||
Assert.True(column3.SequenceEqual([99L, 99L, 99L, 99L, 99L, 100L, 100L, 100L, 100L, 100L])); | ||
}); | ||
} | ||
|
||
[Fact] | ||
public async Task Merge_Memory_No_Delete_Test() | ||
{ | ||
var query = @"MERGE INTO mytable USING newdata | ||
ON newdata.test = mytable.test | ||
WHEN MATCHED THEN | ||
UPDATE SET | ||
second = newdata.second, | ||
third = newdata.third | ||
WHEN NOT MATCHED BY TARGET | ||
THEN INSERT ( | ||
test, | ||
second, | ||
third | ||
) | ||
VALUES ( | ||
newdata.test, | ||
'inserted data', | ||
99 | ||
)"; | ||
await BaseMergeTest(query, batches => | ||
{ | ||
var column1 = batches.SelectMany(batch => ((Int32Array)batch.Column(0)).Values.ToArray()).OrderBy(i => i).ToArray(); | ||
Assert.True(column1.SequenceEqual([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14])); | ||
var column2 = batches.SelectMany(batch => ((IReadOnlyList<string>)(StringArray)batch.Column(1)).ToArray()).OrderBy(i => i).ToArray(); | ||
Assert.True(column2.SequenceEqual(["0", "1", "2", "3", "4", "hello", "hello", "hello", "hello", "hello", "inserted data", "inserted data", "inserted data", "inserted data", "inserted data"])); | ||
var column3 = batches.SelectMany(batch => ((Int64Array)batch.Column(2)).Values.ToArray()).OrderBy(i => i).ToArray(); | ||
Assert.True(column3.SequenceEqual([0L, 1L, 2L, 3L, 4L, 99L, 99L, 99L, 99L, 99L, 100L, 100L, 100L, 100L, 100L])); | ||
}); | ||
} | ||
|
||
[Fact] | ||
public async Task Merge_Memory_No_Insert_Test() | ||
{ | ||
var query = @"MERGE INTO mytable USING newdata | ||
ON newdata.test = mytable.test | ||
WHEN MATCHED THEN | ||
UPDATE SET | ||
second = newdata.second, | ||
third = newdata.third"; | ||
await BaseMergeTest(query, batches => | ||
{ | ||
var column1 = batches.SelectMany(batch => ((Int32Array)batch.Column(0)).Values.ToArray()).OrderBy(i => i).ToArray(); | ||
Assert.True(column1.SequenceEqual([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])); | ||
var column2 = batches.SelectMany(batch => ((IReadOnlyList<string>)(StringArray)batch.Column(1)).ToArray()).OrderBy(i => i).ToArray(); | ||
Assert.True(column2.SequenceEqual(["0", "1", "2", "3", "4", "hello", "hello", "hello", "hello", "hello"])); | ||
var column3 = batches.SelectMany(batch => ((Int64Array)batch.Column(2)).Values.ToArray()).OrderBy(i => i).ToArray(); | ||
Assert.True(column3.SequenceEqual([0L, 1L, 2L, 3L, 4L, 100L, 100L, 100L, 100L, 100L])); | ||
}); | ||
} | ||
|
||
[Fact] | ||
public async Task Merge_Memory_No_Update_Test() | ||
{ | ||
var query = @"MERGE INTO mytable USING newdata | ||
ON newdata.test = mytable.test | ||
WHEN NOT MATCHED BY TARGET | ||
THEN INSERT ( | ||
test, | ||
second, | ||
third | ||
) | ||
VALUES ( | ||
newdata.test, | ||
'inserted data', | ||
99 | ||
)"; | ||
await BaseMergeTest(query, batches => | ||
{ | ||
var column1 = batches.SelectMany(batch => ((Int32Array)batch.Column(0)).Values.ToArray()).OrderBy(i => i).ToArray(); | ||
Assert.True(column1.SequenceEqual([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14])); | ||
var column2 = batches.SelectMany(batch => ((IReadOnlyList<string>)(StringArray)batch.Column(1)).ToArray()).OrderBy(i => i).ToArray(); | ||
Assert.True(column2.SequenceEqual(["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "inserted data", "inserted data", "inserted data", "inserted data", "inserted data"])); | ||
var column3 = batches.SelectMany(batch => ((Int64Array)batch.Column(2)).Values.ToArray()).OrderBy(i => i).ToArray(); | ||
Assert.True(column3.SequenceEqual([0L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 99L, 99L, 99L, 99L, 99L])); | ||
}); | ||
} | ||
|
||
private async Task BaseMergeTest(string query, Action<IReadOnlyList<RecordBatch>> assertions) | ||
{ | ||
var pair = await TableHelpers.SetupTable($"memory://{Guid.NewGuid():N}", 10); | ||
using var runtime = pair.runtime; | ||
using var table = pair.table; | ||
var allocator = new NativeMemoryAllocator(); | ||
var enumerable = Enumerable.Range(5, 10); | ||
var recordBatchBuilder = new RecordBatch.Builder(allocator) | ||
.Append("test", false, col => col.Int32(arr => arr.AppendRange(enumerable))) | ||
.Append("second", false, col => col.String(arr => arr.AppendRange(enumerable.Select(_ => "hello")))) | ||
.Append("third", false, col => col.Int64(arr => arr.AppendRange(enumerable.Select(_ => 100L)))); | ||
using var rb = recordBatchBuilder.Build(); | ||
await table.MergeAsync(query, [rb], rb.Schema, CancellationToken.None); | ||
Console.WriteLine("merged!"); | ||
var batches = table.QueryAsync(new SelectQuery("select * from deltatable"), CancellationToken.None).ToBlockingEnumerable().ToList(); | ||
assertions(batches); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
using Apache.Arrow; | ||
using DeltaLake.Table; | ||
|
||
namespace DeltaLake.Tests.Table; | ||
public class UpdateTests | ||
{ | ||
private const string UpdateGreaterThanOne = "UPDATE test SET test = test + CAST(1 AS INT) WHERE test > CAST(1 AS INT)"; | ||
private const string UpdateNoPredicate = "UPDATE test SET test = test + CAST(1 AS INT)"; | ||
|
||
private const string UpdatePredicateMiss = "UPDATE test SET test = test + CAST(1 AS INT) WHERE test < CAST(0 as INT)"; | ||
|
||
[Theory] | ||
[InlineData(1, UpdateGreaterThanOne)] | ||
[InlineData(2, UpdateGreaterThanOne)] | ||
[InlineData(10, UpdateGreaterThanOne)] | ||
[InlineData(100, UpdateGreaterThanOne)] | ||
public async Task Memory_Update_Variable_Record_Test( | ||
int length, | ||
string predicate) | ||
{ | ||
var totalValue = length < 2 ? length - 1 : (length - 2) / 2 * (length + 3) + 1; | ||
await BaseUpdateTest($"memory://{Guid.NewGuid():N}", length, predicate, totalValue); | ||
} | ||
|
||
[Theory] | ||
[InlineData(1, UpdateNoPredicate)] | ||
[InlineData(2, UpdateNoPredicate)] | ||
[InlineData(10, UpdateNoPredicate)] | ||
[InlineData(100, UpdateNoPredicate)] | ||
public async Task Memory_Update_No_Predicate_Variable_Record_Test( | ||
int length, | ||
string predicate) | ||
{ | ||
var totalValue = length == 1 ? 1 : length / 2 * (length + 1); | ||
await BaseUpdateTest($"memory://{Guid.NewGuid():N}", length, predicate, totalValue); | ||
} | ||
|
||
[Theory] | ||
[InlineData(1, UpdatePredicateMiss)] | ||
[InlineData(2, UpdatePredicateMiss)] | ||
[InlineData(10, UpdatePredicateMiss)] | ||
[InlineData(100, UpdatePredicateMiss)] | ||
public async Task Memory_Update_Predicate_Miss_Variable_Record_Test( | ||
int length, | ||
string predicate) | ||
{ | ||
var totalValue = length / 2 * (length - 1); | ||
await BaseUpdateTest($"memory://{Guid.NewGuid():N}", length, predicate, totalValue); | ||
} | ||
|
||
private async static Task BaseUpdateTest( | ||
string path, | ||
int length, | ||
string query, | ||
long expectedTotal) | ||
{ | ||
var data = await TableHelpers.SetupTable(path, length); | ||
using var runtime = data.runtime; | ||
using var table = data.table; | ||
await table.UpdateAsync(query, CancellationToken.None); | ||
var queryResult = table.QueryAsync(new SelectQuery("select SUM(test) from test") | ||
{ | ||
TableAlias = "test", | ||
}, | ||
CancellationToken.None).ToBlockingEnumerable().ToList(); | ||
var totalValue = queryResult.Select(rb => ((Int64Array)rb.Column(0)).Sum(i => i!.Value)).Sum(); | ||
var totalRecords = queryResult.Select(s => s.Length).Sum(); | ||
Assert.Equal(1, totalRecords); | ||
Assert.Equal(expectedTotal, totalValue); | ||
} | ||
} |