Skip to content
Merged
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
64 changes: 43 additions & 21 deletions src/cigogne/internal/database.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import gleam/string
import gleam/time/timestamp
import pog

const cigogne_process_name = "cigogne"

pub type DatabaseData {
DatabaseData(
connection: pog.Connection,
Expand All @@ -28,9 +30,9 @@ pub type DatabaseError {
PogTransactionError(error: pog.TransactionError(DatabaseError))
}

const check_table_exist = "SELECT table_name, table_schema
FROM information_schema.tables
WHERE table_type = 'BASE TABLE'
const check_table_exist = "SELECT table_name, table_schema
FROM information_schema.tables
WHERE table_type = 'BASE TABLE'
AND table_name = $1
AND table_schema = $2;"

Expand Down Expand Up @@ -82,25 +84,25 @@ fn connect(
config: config.DatabaseConfig,
) -> Result(pog.Connection, DatabaseError) {
case config {
config.EnvVarConfig ->
envoy.get("DATABASE_URL")
|> result.replace_error(EnvVarUnset("DATABASE_URL"))
|> result.try(connection_from_url)
config.EnvVarConfig -> connection_from_env()
config.UrlDbConfig(url:) -> connection_from_url(url)
config.ConnectionDbConfig(connection:) -> Ok(connection)
config.DetailedDbConfig(host:, user:, password:, port:, name:) -> {
let procname = process.new_name("cigogne-db")
let config =
pog.default_config(procname)
|> apply_if_some(user, pog.user)
|> pog.password(password)
|> apply_if_some(host, pog.host)
|> apply_if_some(port, pog.port)
|> apply_if_some(name, pog.database)
pog.start(config)
|> result.map_error(ActorStartError)
|> result.map(fn(actor) { actor.data })
}
config.DetailedDbConfig(host:, user:, password:, port:, name:) ->
connection_from_config(host:, user:, password:, name:, port:)
}
}

fn connection_from_env() -> Result(pog.Connection, DatabaseError) {
case envoy.get("DATABASE_URL") {
Ok(url) -> connection_from_url(url)
Error(_) ->
connection_from_config(
host: envoy.get("PGHOST") |> option.from_result,
user: envoy.get("PGUSER") |> option.from_result,
password: envoy.get("PGPASSWORD") |> option.from_result,
name: envoy.get("PGDATABASE") |> option.from_result,
port: envoy.get("PGPORT") |> result.try(int.parse) |> option.from_result,
)
}
}

Expand All @@ -115,8 +117,28 @@ fn apply_if_some(
}
}

fn connection_from_config(
host host: option.Option(String),
user user: option.Option(String),
password password: option.Option(String),
name name: option.Option(String),
port port: option.Option(Int),
) -> Result(pog.Connection, DatabaseError) {
let procname = process.new_name(cigogne_process_name)
let config =
pog.default_config(procname)
|> apply_if_some(user, pog.user)
|> pog.password(password)
|> apply_if_some(host, pog.host)
|> apply_if_some(port, pog.port)
|> apply_if_some(name, pog.database)
pog.start(config)
|> result.map_error(ActorStartError)
|> result.map(fn(actor) { actor.data })
}

fn connection_from_url(url: String) -> Result(pog.Connection, DatabaseError) {
let db_process_name = process.new_name("cigogne")
let db_process_name = process.new_name(cigogne_process_name)

pog.url_config(db_process_name, url)
|> result.replace_error(IncorrectConnectionString(url))
Expand Down
47 changes: 45 additions & 2 deletions test/cigogne_test/internal/database_test.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,17 @@ import cigogne/internal/database
import cigogne/migration
import envoy
import gleam/erlang/process
import gleam/int
import gleam/list
import gleam/option
import gleam/result
import pog

// Modify these constants to match your local database setup
const db_host = "localhost"

const db_port = 5432

const db_user = "billuc"

const db_password = option.Some("mysecretpassword")
Expand All @@ -26,7 +31,11 @@ fn db_url() {
option.Some(password) -> ":" <> password
option.None -> ""
}
<> "@localhost:5432/"
<> "@"
<> db_host
<> ":"
<> db_port |> int.to_string
<> "/"
<> db_database
}

Expand All @@ -50,9 +59,43 @@ pub fn init_with_envvar_test() {
let init_res = database.init(config)

envoy.unset("DATABASE_URL")

let assert Ok(init_res) = init_res

assert init_res |> database.migrations_table_exists |> result.is_ok()
assert init_res.migrations_table == migration_table
assert init_res.db_schema == schema
}

pub fn init_with_postgres_envvar_test() {
envoy.set("PGHOST", db_host)
envoy.set("PGUSER", db_user)
envoy.set("PGPASSWORD", db_password |> option.unwrap(""))
envoy.set("PGDATABASE", db_database)
envoy.set("PGPORT", db_port |> int.to_string)

let config =
config.Config(
config.EnvVarConfig,
config.MigrationTableConfig(
option.Some(schema),
option.Some(migration_table),
),
config.MigrationsConfig(
"cigogne",
option.Some("test/migrations"),
[],
option.None,
),
)
let init_res = database.init(config)

envoy.unset("PGHOST")
envoy.unset("PGUSER")
envoy.unset("PGPASSWORD")
envoy.unset("PGDATABASE")
envoy.unset("PGPORT")
let assert Ok(init_res) = init_res
assert init_res |> database.migrations_table_exists |> result.is_ok()
assert init_res.migrations_table == migration_table
assert init_res.db_schema == schema
}
Expand Down