Skip to content

Commit

Permalink
Npgsql: Demonstrate OBJECT type mapping using JsonDocument
Browse files Browse the repository at this point in the history
CrateDB's OBJECT data type can also be communicated using .NET's native
`System.Text.Json.JsonDocument` type.
  • Loading branch information
amotl committed Dec 19, 2024
1 parent be0835d commit 970c259
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 4 deletions.
2 changes: 2 additions & 0 deletions by-language/csharp-npgsql/DemoProgram.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ await Parser.Default.ParseArguments<Options>(args)
await DatabaseWorkloads.BasicConversationExample(conn);
await DatabaseWorkloads.UnnestExample(conn);
await DatabaseWorkloadsMore.AllTypesNativeExample(conn);
await DatabaseWorkloadsMore.ObjectJsonDocumentExample(conn);
// await DatabaseWorkloadsMore.ArrayJsonDocumentExample(conn);
await DatabaseWorkloadsMore.ObjectPocoExample(conn);
await DatabaseWorkloadsMore.ArrayPocoExample(conn);
conn.Close();
Expand Down
79 changes: 75 additions & 4 deletions by-language/csharp-npgsql/DemoTypes.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
#nullable enable
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Reflection;
using System.Text.Json;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Npgsql;
Expand Down Expand Up @@ -57,9 +56,9 @@ public class AllTypesRecord
public class DatabaseWorkloadsMore
{

public static async Task<DataTable> AllTypesNativeExample(NpgsqlConnection conn)
public static async Task ProvisionAllTypes(NpgsqlConnection conn)
{
Console.WriteLine("Running AllTypesNativeExample");
Console.WriteLine("Running ProvisionAllTypes");

// Submit DDL, create database schema.
await using (var cmd = new NpgsqlCommand("DROP TABLE IF EXISTS testdrive.example", conn))
Expand Down Expand Up @@ -169,6 +168,15 @@ INSERT INTO testdrive.example (
cmd.ExecuteNonQuery();
}

}

public static async Task<DataTable> AllTypesNativeExample(NpgsqlConnection conn)
{
Console.WriteLine("Running AllTypesNativeExample");

// Provision data.
await ProvisionAllTypes(conn);

// Query back data.
await using (var cmd = new NpgsqlCommand("SELECT * FROM testdrive.example", conn))
await using (var reader = cmd.ExecuteReader())
Expand All @@ -182,6 +190,69 @@ INSERT INTO testdrive.example (

}

public static async Task<JsonDocument> ObjectJsonDocumentExample(NpgsqlConnection conn)
{
Console.WriteLine("Running ObjectJsonDocumentExample");

// Provision data.
await ProvisionAllTypes(conn);

// This test uses the central DDL, but a blank slate to focus on the test case at hand.
await using (var cmd = new NpgsqlCommand("DELETE FROM testdrive.example", conn))
{
cmd.ExecuteNonQuery();
}

await using (var cmd = new NpgsqlCommand("""
INSERT INTO testdrive.example (
"object"
) VALUES (
@object
)
""", conn))
{
cmd.Parameters.AddWithValue("object", NpgsqlDbType.Json, JsonDocument.Parse("""{"foo":"bar"}"""));
cmd.ExecuteNonQuery();
}

// Flush data.
await using (var cmd = new NpgsqlCommand("REFRESH TABLE testdrive.example", conn))
{
cmd.ExecuteNonQuery();
}

// Query back data.
await using (var cmd = new NpgsqlCommand("SELECT * FROM testdrive.example", conn))
await using (var reader = cmd.ExecuteReader())
{
reader.Read();
var obj = reader.GetFieldValue<JsonDocument>("object");
Console.WriteLine(obj);
return obj;
}
}

public static async Task<List<JsonDocument>> ArrayJsonDocumentExample(NpgsqlConnection conn)
{
Console.WriteLine("Running ArrayJsonDocumentExample");

// Provision data.
await ProvisionAllTypes(conn);

// Query back data.
await using (var cmd = new NpgsqlCommand("SELECT * FROM testdrive.example", conn))
await using (var reader = cmd.ExecuteReader())
{
reader.Read();
// TODO: System.InvalidCastException: Reading as 'System.Text.Json.JsonDocument' or [1]
// is not supported for fields having DataTypeName 'character varying[]'.
// [1] `System.Collections.Generic.List`1[[System.Text.Json.JsonDocument]`
var obj = reader.GetFieldValue<List<JsonDocument>>("array");
Console.WriteLine(obj);
return obj;
}
}

public static async Task ProvisionPoco(NpgsqlConnection conn)
{
/***
Expand Down
14 changes: 14 additions & 0 deletions by-language/csharp-npgsql/tests/DemoProgramTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
using Npgsql;
using Xunit;
Expand Down Expand Up @@ -168,6 +169,19 @@ public async Task TestContainerTypesExample()

}

[Fact]
public async Task TestObjectJsonDocumentExample()
{
var conn = fixture.Db;

// Invoke database workload.
var task = DatabaseWorkloadsMore.ObjectJsonDocumentExample(conn);
var obj = await task.WaitAsync(TimeSpan.FromSeconds(0.5));

// Validate the outcome.
Assert.Equal("""{"foo":"bar"}""", JsonSerializer.Serialize(obj));
}

[Fact]
public async Task TestObjectPocoExample()
{
Expand Down

0 comments on commit 970c259

Please sign in to comment.