From eb8ccba905e5123b527b651afb90b4e84692d5b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20St=C3=B6ger?= Date: Mon, 17 Feb 2025 13:15:05 +0100 Subject: [PATCH] Support "real" (float32) arrays --- src/Common.fs | 13 +++++++++++ src/Npgsql.FSharp.fs | 2 ++ tests/NpgsqlFSharpTests.fs | 44 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+) diff --git a/src/Common.fs b/src/Common.fs index f6c7720..1c71842 100644 --- a/src/Common.fs +++ b/src/Common.fs @@ -34,6 +34,7 @@ type SqlValue = | IntArray of int array | ShortArray of int16 array | LongArray of int64 array + | RealArray of float32 array | DoubleArray of double array | DecimalArray of decimal array | Point of NpgsqlPoint @@ -147,6 +148,9 @@ type Sql() = static member int64Array(value: int64[]) = SqlValue.LongArray value static member int64ArrayOrNone(value: int64[] option) = Utils.sqlMap value Sql.int64Array static member int64ArrayOrValueNone(value: int64[] voption) = Utils.sqlValueMap value Sql.int64Array + static member realArray(value: float32[]) = SqlValue.RealArray value + static member realArrayOrNone(value: float32[] option) = Utils.sqlMap value Sql.realArray + static member realArrayOrValueNone(value: float32[] voption) = Utils.sqlValueMap value Sql.realArray static member doubleArray(value: double[]) = SqlValue.DoubleArray value static member doubleArrayOrNone(value: double[] option) = Utils.sqlMap value Sql.doubleArray static member doubleArrayOrValueNone(value: double[] voption) = Utils.sqlValueMap value Sql.doubleArray @@ -283,6 +287,15 @@ type RowReader(reader: NpgsqlDataReader) = member this.int64ArrayOrValueNone(column: string) : int64[] voption = this.fieldValueOrValueNone(column) + member this.realArray(column: string) : float32[] = + this.fieldValue(column) + + member this.realArrayOrNone(column: string) : float32[] option = + this.fieldValueOrNone(column) + + member this.realArrayOrValueNone(column: string) : float32[] voption = + this.fieldValueOrValueNone(column) + member this.doubleArray(column: string) : double[] = this.fieldValue(column) diff --git a/src/Npgsql.FSharp.fs b/src/Npgsql.FSharp.fs index fef063c..e7f7f3f 100644 --- a/src/Npgsql.FSharp.fs +++ b/src/Npgsql.FSharp.fs @@ -238,6 +238,7 @@ module Sql = | SqlValue.IntArray x -> add x (NpgsqlDbType.Array ||| NpgsqlDbType.Integer) | SqlValue.ShortArray x -> add x (NpgsqlDbType.Array ||| NpgsqlDbType.Smallint) | SqlValue.LongArray x -> add x (NpgsqlDbType.Array ||| NpgsqlDbType.Bigint) + | SqlValue.RealArray x -> add x (NpgsqlDbType.Array ||| NpgsqlDbType.Real) | SqlValue.DoubleArray x -> add x (NpgsqlDbType.Array ||| NpgsqlDbType.Double) | SqlValue.DecimalArray x -> add x (NpgsqlDbType.Array ||| NpgsqlDbType.Numeric) | SqlValue.Real x -> add x NpgsqlDbType.Real @@ -286,6 +287,7 @@ module Sql = | SqlValue.IntArray x -> add x (NpgsqlDbType.Array ||| NpgsqlDbType.Integer) | SqlValue.ShortArray x -> add x (NpgsqlDbType.Array ||| NpgsqlDbType.Smallint) | SqlValue.LongArray x -> add x (NpgsqlDbType.Array ||| NpgsqlDbType.Bigint) + | SqlValue.RealArray x -> add x (NpgsqlDbType.Array ||| NpgsqlDbType.Real) | SqlValue.DoubleArray x -> add x (NpgsqlDbType.Array ||| NpgsqlDbType.Double) | SqlValue.DecimalArray x -> add x (NpgsqlDbType.Array ||| NpgsqlDbType.Numeric) | SqlValue.Real x -> add x NpgsqlDbType.Real diff --git a/tests/NpgsqlFSharpTests.fs b/tests/NpgsqlFSharpTests.fs index 418c95a..6712ebc 100644 --- a/tests/NpgsqlFSharpTests.fs +++ b/tests/NpgsqlFSharpTests.fs @@ -28,6 +28,11 @@ type IntArrayTest = { integers: int array } +type RealArrayTest = { + id: int + reals: float32 array +} + type DoubleArrayTest = { id: int doubles: double array @@ -68,6 +73,7 @@ let buildDatabase() : PostgreSqlContainer = let createStringArrayTable = "create table if not exists string_array_test (id int, values text [])" let createUuidArrayTable = "create table if not exists uuid_array_test (id int, values uuid [])" let createIntArrayTable = "create table if not exists int_array_test (id int, integers int [])" + let createRealArrayTable = "create table if not exists real_array_test (id int, reals real [])" let createDoubleArrayTable = "create table if not exists double_array_test (id int, doubles double precision [])" let createDecimalArrayTable = "create table if not exists decimal_array_test (id int, decimals money [])" let createPointTable = "create table if not exists point_test (id int, test_point point)" @@ -89,6 +95,7 @@ let buildDatabase() : PostgreSqlContainer = createStringArrayTable, [ ] createExtensionHStore, [ ] createIntArrayTable, [ ] + createRealArrayTable, [ ] createDoubleArrayTable, [ ] createDecimalArrayTable, [ ] createExtensionUuid, [ ] @@ -1440,6 +1447,43 @@ from ( Expect.equal expected table "All rows" } + test "Handle real Array" { + let a = [| 1.f; 2.f |] + let b = [| for i in 0..10 do yield (float32 i) |] + let c : float32 array = [||] + let seedDatabase (connection: string) = + connection + |> Sql.connect + |> Sql.executeTransaction [ + "INSERT INTO real_array_test (id, reals) values (@id, @reals)", [ + [ "@id", Sql.int 1; "@reals", Sql.realArray a ] + [ "@id", Sql.int 2; "@reals", Sql.realArray b ] + [ "@id", Sql.int 3; "@reals", Sql.realArray c ] + ] + ] + |> ignore + + let db = buildDatabase() + seedDatabase (db.GetConnectionString()) + + let table = + db.GetConnectionString() + |> Sql.connect + |> Sql.query "SELECT * FROM real_array_test" + |> Sql.execute (fun read -> { + id = read.int "id" + reals = read.realArray "reals" + }) + + let expected = [ + { id = 1; reals = a } + { id = 2; reals = b } + { id = 3; reals = c } + ] + + Expect.equal expected table "All rows from `real_array_test` table" + } + test "Handle double Array" { let a = [| 1.; 2. |] let b = [| for i in 0..10 do yield (double i) |]