Skip to content

Commit 01823ea

Browse files
committed
Npgsql: Validate marshalling GEO_SHAPE types as STRING
1 parent c34838e commit 01823ea

File tree

2 files changed

+113
-8
lines changed

2 files changed

+113
-8
lines changed

by-language/csharp-npgsql/DemoTypes.cs

+66-6
Original file line numberDiff line numberDiff line change
@@ -114,9 +114,9 @@ INSERT INTO testdrive.example (
114114
timestamp_notz,
115115
ip,
116116
""array"",
117-
-- ""object"",
117+
""object"",
118118
geopoint,
119-
-- geoshape,
119+
geoshape,
120120
float_vector
121121
) VALUES (
122122
@null_integer,
@@ -133,9 +133,9 @@ INSERT INTO testdrive.example (
133133
@timestamp_notz,
134134
@ip,
135135
@array,
136-
-- @object,
136+
@object,
137137
@geopoint,
138-
-- @egoshape,
138+
@geoshape,
139139
@float_vector
140140
);
141141
", conn))
@@ -157,9 +157,9 @@ 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});
161-
// FIXME: Npgsql.PostgresException : XX000: line 38:9: no viable alternative at input 'VALUES
162-
// cmd.Parameters.AddWithValue("geoshape", "POLYGON ((5 5, 10 5, 10 10, 5 10, 5 5))");
162+
cmd.Parameters.AddWithValue("geoshape", "POLYGON ((5 5, 10 5, 10 10, 5 10, 5 5))");
163163
cmd.Parameters.AddWithValue("float_vector", new List<double> {1.1, 2.2, 3.3});
164164
cmd.ExecuteNonQuery();
165165
}
@@ -183,6 +183,66 @@ INSERT INTO testdrive.example (
183183

184184
}
185185

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

188248
}

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

+47-2
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,16 +112,60 @@ 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
122+
// TODO: Unlock native data types?
123+
// GEO_POINT and GEO_SHAPE types can be marshalled back and forth using STRING.
124+
// GEO_POINT is using a tuple format, GEO_SHAPE is using the GeoJSON format.
117125
// Assert.Equal(new List<double>{85.43, 66.23}, row["geopoint"]); // TODO
118126
Assert.Equal("(85.42999997735023,66.22999997343868)", row["geopoint"].ToString()); // FIXME
119-
Assert.Equal(DBNull.Value, row["geoshape"]); // FIXME
127+
Assert.Equal(@"{""coordinates"":[[[5.0,5.0],[5.0,10.0],[10.0,10.0],[10.0,5.0],[5.0,5.0]]],""type"":""Polygon""}", row["geoshape"]);
120128

121129
// Vector type
122130
Assert.Equal((new List<double>{1.1, 2.2, 3.3}).Select(d => (float) d).ToArray(), row["float_vector"]);
123131
}
124132

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

0 commit comments

Comments
 (0)