Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix enum array error #47

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# CHANGELOG

## Unreleased

- Fixed a bug where queries with enum arrays would cause an error.
([Leah Ulmschneider](https://github.com/leah-u))

## v2.0.4 - 2024-12-04

- Replace deprecated `gleam/regex` module with `gleam/regexp`.
Expand Down
60 changes: 60 additions & 0 deletions birdie_snapshots/enum_array_decoding.accepted
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
---
version: 1.2.3
title: enum array decoding
file: ./test/squirrel_test.gleam
test_name: enum_array_decoding_test
---
import decode/zero
import pog

/// A row you get from running the `query` query
/// defined in `query.sql`.
///
/// > 🐿️ This type definition was generated automatically using v-test of the
/// > [squirrel package](https://github.com/giacomocavalieri/squirrel).
///
pub type QueryRow {
QueryRow(res: List(SquirrelColour))
}

/// Runs the `query` query
/// defined in `query.sql`.
///
/// > 🐿️ This function was generated automatically using v-test of
/// > the [squirrel package](https://github.com/giacomocavalieri/squirrel).
///
pub fn query(db) {
let decoder = {
use res <- zero.field(0, zero.list(squirrel_colour_decoder()))
zero.success(QueryRow(res:))
}

let query = "select array['red'::squirrel_colour] as res"

pog.query(query)
|> pog.returning(zero.run(_, decoder))
|> pog.execute(db)
}

// --- Enums -------------------------------------------------------------------

/// Corresponds to the Postgres `squirrel_colour` enum.
///
/// > 🐿️ This type definition was generated automatically using v-test of the
/// > [squirrel package](https://github.com/giacomocavalieri/squirrel).
///
pub type SquirrelColour {
LightBrown
Grey
Red
}

fn squirrel_colour_decoder() {
use variant <- zero.then(zero.string)
case variant {
"light brown" -> zero.success(LightBrown)
"grey" -> zero.success(Grey)
"red" -> zero.success(Red)
_ -> zero.failure(LightBrown, "SquirrelColour")
}
}
13 changes: 10 additions & 3 deletions src/squirrel/internal/database/postgres.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@ select
else elem.typname
end as type,

-- The oid of the type or the array item type.
case
when elem.typname is null then type.oid
else elem.oid
end as oid,

-- Tells us how to interpret the first column: if this is true then the first
-- column is the type of the elements of the array type.
-- Otherwise it means we've found a base type.
Expand Down Expand Up @@ -664,13 +670,14 @@ fn find_gleam_type(query: UntypedQuery, oid: Int) -> Db(gleam.Type) {
let params = [pg.Parameter(<<oid:32>>)]
use res <- eval.try(run_query(find_postgres_type_query(), params, [23]))

// We know the output must only contain two values: the name and a boolean to
// check wether it is an array or not.
// We know the output must only contain four values: the name, the oid, a boolean to
// check wether it is an array or not and the type of the type / array item.
// It's safe to assert because this query is hard coded in our code and the
// output shape cannot change without us changing that query.
let assert [[name, is_array, kind]] = res
let assert [[name, oid, is_array, kind]] = res
let assert Ok(name) = bit_array.to_string(name)
let assert Ok(kind) = bit_array.to_string(kind)
let assert <<oid:size(32)>> = oid

use type_ <- eval.try(case kind {
"e" -> resolve_enum_type(name, oid)
Expand Down
6 changes: 6 additions & 0 deletions test/squirrel_test.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,12 @@ pub fn enum_encoding_test() {
|> birdie.snap(title: "enum encoding")
}

pub fn enum_array_decoding_test() {
"select array['red'::squirrel_colour] as res"
|> should_codegen
|> birdie.snap(title: "enum array decoding")
}

// --- CODEGEN STRUCTURE TESTS -------------------------------------------------
// This is a group of tests to ensure the generated code has some specific
// structure (e.g. the names and comments are what we expect...)
Expand Down
Loading