Skip to content

Commit 7d76d60

Browse files
committed
Npgsql: Validate marshalling OBJECT types as STRING, and query it
1 parent 5563f07 commit 7d76d60

File tree

2 files changed

+106
-3
lines changed

2 files changed

+106
-3
lines changed

by-language/csharp-npgsql/DemoTypes.cs

+63-2
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ INSERT INTO testdrive.example (
114114
timestamp_notz,
115115
ip,
116116
""array"",
117-
-- ""object"",
117+
""object"",
118118
geopoint,
119119
-- geoshape,
120120
float_vector
@@ -133,7 +133,7 @@ INSERT INTO testdrive.example (
133133
@timestamp_notz,
134134
@ip,
135135
@array,
136-
-- @object,
136+
@object,
137137
@geopoint,
138138
-- @egoshape,
139139
@float_vector
@@ -157,6 +157,7 @@ INSERT INTO testdrive.example (
157157
cmd.Parameters.AddWithValue("array", new List<string>{"foo", "bar"});
158158
// FIXME: System.NotSupportedException: Cannot resolve 'hstore' to a fully qualified datatype name. The datatype was not found in the current database info.
159159
// cmd.Parameters.AddWithValue("object", new Dictionary<string, string>(){{"foo", "bar"}});
160+
cmd.Parameters.AddWithValue("object", @"{""foo"": ""bar""}");
160161
cmd.Parameters.AddWithValue("geopoint", new List<double>{85.43, 66.23});
161162
// FIXME: Npgsql.PostgresException : XX000: line 38:9: no viable alternative at input 'VALUES
162163
// cmd.Parameters.AddWithValue("geoshape", "POLYGON ((5 5, 10 5, 10 10, 5 10, 5 5))");
@@ -183,6 +184,66 @@ INSERT INTO testdrive.example (
183184

184185
}
185186

187+
public static async Task<DataTable> ContainerTypesExample(NpgsqlConnection conn)
188+
{
189+
Console.WriteLine("Running AllTypesExample");
190+
191+
// Submit DDL, create database schema.
192+
await using (var cmd = new NpgsqlCommand("DROP TABLE IF EXISTS testdrive.container", conn))
193+
{
194+
cmd.ExecuteNonQuery();
195+
}
196+
197+
await using (var cmd = new NpgsqlCommand(@"
198+
CREATE TABLE testdrive.container (
199+
-- Container types
200+
""array"" ARRAY(STRING),
201+
""object"" OBJECT(DYNAMIC)
202+
);
203+
", conn))
204+
{
205+
cmd.ExecuteNonQuery();
206+
}
207+
208+
// Insert single data point.
209+
await using (var cmd = new NpgsqlCommand(@"
210+
INSERT INTO testdrive.container (
211+
""array"",
212+
""object""
213+
) VALUES (
214+
@array,
215+
@object
216+
);
217+
", conn))
218+
{
219+
Console.WriteLine(cmd);
220+
// FIXME: While doing conversations with ARRAY types works natively,
221+
// it doesn't work for OBJECT types.
222+
// Yet, they can be submitted as STRING in JSON format.
223+
cmd.Parameters.AddWithValue("array", new List<string>{"foo", "bar"});
224+
cmd.Parameters.AddWithValue("object", @"{""foo"": ""bar""}");
225+
cmd.ExecuteNonQuery();
226+
}
227+
228+
// Flush data.
229+
await using (var cmd = new NpgsqlCommand("REFRESH TABLE testdrive.container", conn))
230+
{
231+
cmd.ExecuteNonQuery();
232+
}
233+
234+
// Query back data.
235+
await using (var cmd = new NpgsqlCommand("SELECT * FROM testdrive.container", conn))
236+
await using (var reader = cmd.ExecuteReader())
237+
{
238+
var dataTable = new DataTable();
239+
dataTable.Load(reader);
240+
var payload = JsonConvert.SerializeObject(dataTable);
241+
Console.WriteLine(payload);
242+
return (DataTable) dataTable;
243+
}
244+
245+
}
246+
186247
}
187248

188249
}

by-language/csharp-npgsql/tests/DemoProgramTest.cs

+43-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Data;
34
using System.Linq;
45
using System.Threading.Tasks;
56
using Npgsql;
@@ -111,8 +112,12 @@ public async Task TestAllTypesExample()
111112
Assert.Equal("127.0.0.1", row["ip"]);
112113

113114
// Container types
115+
// FIXME: While doing conversations with ARRAY types works natively,
116+
// it doesn't work for OBJECT types.
117+
// Yet, they can be submitted as STRING in JSON format.
114118
Assert.Equal(new List<string>{"foo", "bar"}, row["array"]);
115-
Assert.Equal(DBNull.Value, row["object"]); // FIXME
119+
Assert.Equal(@"{""foo"":""bar""}", row["object"]);
120+
116121
// Geospatial types
117122
// Assert.Equal(new List<double>{85.43, 66.23}, row["geopoint"]); // TODO
118123
Assert.Equal("(85.42999997735023,66.22999997343868)", row["geopoint"].ToString()); // FIXME
@@ -122,5 +127,42 @@ public async Task TestAllTypesExample()
122127
Assert.Equal((new List<double>{1.1, 2.2, 3.3}).Select(d => (float) d).ToArray(), row["float_vector"]);
123128
}
124129

130+
[Fact]
131+
public async Task TestContainerTypesExample()
132+
{
133+
var conn = fixture.Db;
134+
135+
// Invoke database workload.
136+
var task = DatabaseWorkloadsMore.ContainerTypesExample(conn);
137+
var dt = await task.WaitAsync(TimeSpan.FromSeconds(0.5));
138+
139+
// Check results.
140+
var row = dt.Rows[0];
141+
// FIXME: While doing conversations with ARRAY types works natively,
142+
// it doesn't work for OBJECT types.
143+
// Yet, they can be submitted as STRING in JSON format.
144+
Assert.Equal(new List<string>{"foo", "bar"}, row["array"]);
145+
Assert.Equal(@"{""foo"":""bar""}", row["object"]);
146+
147+
// Run a special query indexing into ARRAY types.
148+
await using (var cmd = new NpgsqlCommand(@"SELECT ""array[2]"" AS foo FROM testdrive.container", conn))
149+
await using (var reader = cmd.ExecuteReader())
150+
{
151+
var dataTable = new DataTable();
152+
dataTable.Load(reader);
153+
Assert.Equal("bar", dataTable.Rows[0]["foo"]);
154+
}
155+
156+
// Run a special query indexing into OBJECT types.
157+
await using (var cmd = new NpgsqlCommand(@"SELECT ""object['foo']"" AS foo FROM testdrive.container", conn))
158+
await using (var reader = cmd.ExecuteReader())
159+
{
160+
var dataTable = new DataTable();
161+
dataTable.Load(reader);
162+
Assert.Equal("bar", dataTable.Rows[0]["foo"]);
163+
}
164+
165+
}
166+
125167
}
126168
}

0 commit comments

Comments
 (0)