🐿️ Type safe SQL in Gleam
77

Configure Feed

Select the types of activity you want to include in your feed.

add failing test for numeric types

Giacomo Cavalieri (Jul 14, 2025, 4:43 PM +0200) 3fb85084 eeadb611

+44 -7
+44 -7
test/integration_test.gleam
··· 3 3 import filepath 4 4 import gleam/bool 5 5 import gleam/erlang/atom 6 + import gleam/int 6 7 import gleam/io 7 8 import gleam/list 8 9 import gleam/regexp ··· 13 14 14 15 /// An integration test for a specific postgres type. 15 16 /// 16 - type TestType { 17 + type TestCase { 18 + /// This tests squirrel on a fixed set of parametrised queries doing 19 + /// insertions and selects. To do so it creates some Gleam code that uses 20 + /// Gleam values as parameters to the query. 21 + /// 17 22 TestType(postgres_type: String, values: List(TestValue)) 23 + 24 + /// This tests squirrel running a fixed query with no parameters. And it 25 + /// checks the value you get back from the query to match the given 26 + /// `expected_value`. 27 + /// 28 + TestQuery(query: String) 18 29 } 19 30 20 31 /// How a tested value looks in gleam code when it is fed into a query or ··· 62 73 TestType("float4", [TestValue("1.0")]), 63 74 TestType("float8", [TestValue("1.0")]), 64 75 TestType("numeric", [TestValue("1.0")]), 76 + TestQuery("select 1::numeric"), 65 77 // Uuid 66 78 TestType("uuid", [TestValue("uuid.v7()")]), 67 79 // Bytea ··· 134 146 } 135 147 136 148 fn run_integration_tests( 137 - values: List(TestType), 149 + values: List(TestCase), 138 150 ) -> Result(Result(String, #(Int, String)), simplifile.FileError) { 139 151 let integration_test_project = filepath.join(".", "integration_test_project") 140 152 let _ = simplifile.create_directory(integration_test_project) ··· 144 156 145 157 scaffold_gleam_project(dir) 146 158 let code = { 147 - use code, TestType(postgres_type, values) <- list.fold(values, "") 148 - let table_name = safe_name(postgres_type) <> "_table" 149 - create_database_table(table_name, postgres_type) 150 - let assertions = 151 - create_query_files_and_assertions(postgres_type, table_name, values, dir) 159 + use code, test_case <- list.fold(values, "") 160 + let assertions = setup_and_generate_code(for: test_case, in: dir) 152 161 code <> "\n\n" <> assertions 153 162 } 154 163 write_main(code, to: dir) 155 164 test_project(dir) 156 165 } 157 166 167 + fn setup_and_generate_code(for test_case: TestCase, in dir: String) -> String { 168 + case test_case { 169 + TestQuery(query:) -> create_query_files_and_assertions_for_query(query, dir) 170 + TestType(postgres_type:, values:) -> { 171 + let table_name = safe_name(postgres_type) <> "_table" 172 + create_database_table(table_name, postgres_type) 173 + create_query_files_and_assertions(postgres_type, table_name, values, dir) 174 + } 175 + } 176 + } 177 + 158 178 fn create_database_table(table_name: String, postgres_type: String) -> Nil { 159 179 let drop = "drop table if exists " <> table_name 160 180 let create = "create table if not exists " <> table_name <> "( ··· 267 287 268 288 string.join(assertions, with: "\n") 269 289 } 290 + 291 + fn create_query_files_and_assertions_for_query( 292 + query: String, 293 + dir: String, 294 + ) -> String { 295 + let src_dir = filepath.join(dir, "src") 296 + let sql_dir = filepath.join(src_dir, "sql") 297 + let query_name = "query_" <> int.to_string(unique_integer()) 298 + let assert Ok(_) = 299 + simplifile.write(query, to: filepath.join(sql_dir, query_name <> ".sql")) 300 + 301 + "let assert Ok(_) = sql.<query>(db)" 302 + |> string.replace(each: "<query>", with: query_name) 303 + } 304 + 305 + @external(erlang, "squirrel_ffi", "unique") 306 + fn unique_integer() -> Int 270 307 271 308 /// Writes the entry point of the Gleam project that will connect to the 272 309 /// database and run all the assertions testing the generated squirrel code.