From 3ab7f6a103539c78609e6df6e1957e7536a30f79 Mon Sep 17 00:00:00 2001 From: dvic Date: Thu, 30 Jan 2025 09:23:57 +0100 Subject: [PATCH] Add support for decoding using column names --- src/sqlight.gleam | 22 ++++++++++++++++++++++ src/sqlight_ffi.erl | 13 ++++++++++++- src/sqlight_ffi.js | 10 ++++++++++ test/sqlight_test.gleam | 10 ++++++++++ 4 files changed, 54 insertions(+), 1 deletion(-) diff --git a/src/sqlight.gleam b/src/sqlight.gleam index 0d6f238..6817926 100644 --- a/src/sqlight.gleam +++ b/src/sqlight.gleam @@ -389,6 +389,20 @@ pub fn query( Ok(rows) } +pub fn query_entries( + sql: String, + on connection: Connection, + with arguments: List(Value), + expecting decoder: Decoder(t), +) -> Result(List(t), Error) { + use rows <- result.then(run_query_entries(sql, connection, arguments)) + use rows <- result.then( + list.try_map(over: rows, with: fn(row) { decode.run(row, decoder) }) + |> result.map_error(decode_error), + ) + Ok(rows) +} + @external(erlang, "sqlight_ffi", "query") @external(javascript, "./sqlight_ffi.js", "query") fn run_query( @@ -397,6 +411,14 @@ fn run_query( c: List(Value), ) -> Result(List(Dynamic), Error) +@external(erlang, "sqlight_ffi", "query_entries") +@external(javascript, "./sqlight_ffi.js", "query_entries") +fn run_query_entries( + a: String, + b: Connection, + c: List(Value), +) -> Result(List(Dynamic), Error) + @external(erlang, "sqlight_ffi", "coerce_value") @external(javascript, "./sqlight_ffi.js", "coerce_value") fn coerce_value(a: a) -> Value diff --git a/src/sqlight_ffi.erl b/src/sqlight_ffi.erl index e86247e..a9035ab 100644 --- a/src/sqlight_ffi.erl +++ b/src/sqlight_ffi.erl @@ -1,7 +1,7 @@ -module(sqlight_ffi). -export([ - status/0, query/3, exec/2, coerce_value/1, coerce_blob/1, null/0, open/1, close/1 + status/0, query/3, query_entries/3, exec/2, coerce_value/1, coerce_blob/1, null/0, open/1, close/1 ]). open(Name) -> @@ -24,6 +24,17 @@ query(Sql, Connection, Arguments) when is_binary(Sql) -> Rows -> {ok, lists:map(fun erlang:list_to_tuple/1, Rows)} end. +query_entries(Sql, Connection, Arguments) when is_binary(Sql) -> + case esqlite3:prepare(Connection, Sql, Arguments) of + {error, Code} -> to_error(Connection, Code); + {ok, Stmt} -> + ColumnNames = esqlite3:column_names(Stmt), + case esqlite3:fetchall(Stmt) of + {error, Code} -> to_error(Connection, Code); + Rows -> {ok, lists:map(fun(Row) -> maps:from_list(lists:zip(ColumnNames, Row)) end, Rows)} + end + end. + exec(Sql, Connection) -> case esqlite3:exec(Connection, Sql) of {error, Code} -> to_error(Connection, Code); diff --git a/src/sqlight_ffi.js b/src/sqlight_ffi.js index 14f5b74..52f8c6e 100644 --- a/src/sqlight_ffi.js +++ b/src/sqlight_ffi.js @@ -43,6 +43,16 @@ export function query(sql, connection, parameters) { return new Ok(List.fromArray(rows)); } +export function query_entries(sql, connection, parameters) { + let rows; + try { + rows = connection.queryEntries(sql, parameters.toArray()); + } catch (error) { + return convert_error(error); + } + return new Ok(List.fromArray(rows)); +} + export function null_() { return undefined; } diff --git a/test/sqlight_test.gleam b/test/sqlight_test.gleam index 84757cb..1579267 100644 --- a/test/sqlight_test.gleam +++ b/test/sqlight_test.gleam @@ -73,6 +73,16 @@ pub fn query_2_test() { ) } +pub fn query_entries_test() { + use conn <- connect() + let assert Ok([#(1337, "wibble")]) = + sqlight.query_entries("select 1337 as col_a, 'wibble' as col_b", conn, [], { + use col_b <- decode.field("col_b", decode.string) + use col_a <- decode.field("col_a", decode.int) + decode.success(#(col_a, col_b)) + }) +} + pub fn bind_int_test() { use conn <- connect() let assert Ok([12_345]) =