gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[libeufin] branch master updated (b88be146 -> 42eb74f8)


From: gnunet
Subject: [libeufin] branch master updated (b88be146 -> 42eb74f8)
Date: Wed, 03 Apr 2024 17:56:54 +0200

This is an automated email from the git hooks/post-receive script.

antoine pushed a change to branch master
in repository libeufin.

    from b88be146 Fix printing
     new 661e1b32 Refactor db logic
     new 42eb74f8 clean postgres URI logic

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 bank/src/main/kotlin/tech/libeufin/bank/Config.kt  |   1 +
 bank/src/main/kotlin/tech/libeufin/bank/Main.kt    |   1 +
 .../kotlin/tech/libeufin/bank/db/AccountDAO.kt     |   1 +
 .../kotlin/tech/libeufin/bank/db/CashoutDAO.kt     |   1 +
 .../kotlin/tech/libeufin/bank/db/ConversionDAO.kt  |   4 +-
 .../main/kotlin/tech/libeufin/bank/db/Database.kt  |   1 +
 .../kotlin/tech/libeufin/bank/db/ExchangeDAO.kt    |   1 +
 .../src/main/kotlin/tech/libeufin/bank/db/GcDAO.kt |   1 +
 .../tech/libeufin/bank/db/NotificationWatcher.kt   |   1 +
 .../main/kotlin/tech/libeufin/bank/db/TanDAO.kt    |   2 +-
 .../main/kotlin/tech/libeufin/bank/db/TokenDAO.kt  |   3 +-
 .../kotlin/tech/libeufin/bank/db/TransactionDAO.kt |   1 +
 .../kotlin/tech/libeufin/bank/db/WithdrawalDAO.kt  |   1 +
 bank/src/test/kotlin/AmountTest.kt                 |   1 +
 bank/src/test/kotlin/DatabaseTest.kt               |   1 +
 bank/src/test/kotlin/GcTest.kt                     |   1 +
 bank/src/test/kotlin/StatsTest.kt                  |   1 +
 bank/src/test/kotlin/helpers.kt                    |   1 +
 common/build.gradle                                |   2 +
 common/src/main/kotlin/DB.kt                       | 355 ---------------------
 common/src/main/kotlin/db/DbPool.kt                |  78 +++++
 common/src/main/kotlin/db/config.kt                |  95 ++++++
 common/src/main/kotlin/db/schema.kt                |  89 ++++++
 common/src/main/kotlin/{iban.kt => db/types.kt}    |  27 +-
 common/src/main/kotlin/db/utils.kt                 | 124 +++++++
 common/src/test/kotlin/ConfigTest.kt               |  17 +
 .../src/main/kotlin/tech/libeufin/nexus/DbInit.kt  |   1 +
 nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt  |   1 +
 .../main/kotlin/tech/libeufin/nexus/db/Database.kt |   1 +
 .../kotlin/tech/libeufin/nexus/db/InitiatedDAO.kt  |   1 +
 .../kotlin/tech/libeufin/nexus/db/PaymentDAO.kt    |   1 +
 nexus/src/test/kotlin/helpers.kt                   |   1 +
 testbench/src/test/kotlin/IntegrationTest.kt       |   1 +
 testbench/src/test/kotlin/MigrationTest.kt         |   1 +
 34 files changed, 445 insertions(+), 374 deletions(-)
 delete mode 100644 common/src/main/kotlin/DB.kt
 create mode 100644 common/src/main/kotlin/db/DbPool.kt
 create mode 100644 common/src/main/kotlin/db/config.kt
 create mode 100644 common/src/main/kotlin/db/schema.kt
 copy common/src/main/kotlin/{iban.kt => db/types.kt} (63%)
 create mode 100644 common/src/main/kotlin/db/utils.kt

diff --git a/bank/src/main/kotlin/tech/libeufin/bank/Config.kt 
b/bank/src/main/kotlin/tech/libeufin/bank/Config.kt
index f48a1b35..769e29de 100644
--- a/bank/src/main/kotlin/tech/libeufin/bank/Config.kt
+++ b/bank/src/main/kotlin/tech/libeufin/bank/Config.kt
@@ -23,6 +23,7 @@ import kotlinx.serialization.json.Json
 import org.slf4j.Logger
 import org.slf4j.LoggerFactory
 import tech.libeufin.common.*
+import tech.libeufin.common.db.*
 import java.nio.file.Path
 import java.time.Duration
 
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/Main.kt 
b/bank/src/main/kotlin/tech/libeufin/bank/Main.kt
index 31488c03..8dafbce7 100644
--- a/bank/src/main/kotlin/tech/libeufin/bank/Main.kt
+++ b/bank/src/main/kotlin/tech/libeufin/bank/Main.kt
@@ -54,6 +54,7 @@ import org.slf4j.event.Level
 import tech.libeufin.bank.db.AccountDAO.*
 import tech.libeufin.bank.db.Database
 import tech.libeufin.common.*
+import tech.libeufin.common.db.*
 import java.net.InetAddress
 import java.sql.SQLException
 import java.util.zip.DataFormatException
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/db/AccountDAO.kt 
b/bank/src/main/kotlin/tech/libeufin/bank/db/AccountDAO.kt
index a3a5d8e5..5f102ccc 100644
--- a/bank/src/main/kotlin/tech/libeufin/bank/db/AccountDAO.kt
+++ b/bank/src/main/kotlin/tech/libeufin/bank/db/AccountDAO.kt
@@ -21,6 +21,7 @@ package tech.libeufin.bank.db
 
 import tech.libeufin.bank.*
 import tech.libeufin.common.*
+import tech.libeufin.common.db.*
 import tech.libeufin.common.crypto.*
 import java.time.Instant
 
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/db/CashoutDAO.kt 
b/bank/src/main/kotlin/tech/libeufin/bank/db/CashoutDAO.kt
index 958d2b33..799d466a 100644
--- a/bank/src/main/kotlin/tech/libeufin/bank/db/CashoutDAO.kt
+++ b/bank/src/main/kotlin/tech/libeufin/bank/db/CashoutDAO.kt
@@ -21,6 +21,7 @@ package tech.libeufin.bank.db
 
 import tech.libeufin.bank.*
 import tech.libeufin.common.*
+import tech.libeufin.common.db.*
 import java.time.Instant
 
 /** Data access logic for cashout operations */
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/db/ConversionDAO.kt 
b/bank/src/main/kotlin/tech/libeufin/bank/db/ConversionDAO.kt
index a76b7630..3e025a0c 100644
--- a/bank/src/main/kotlin/tech/libeufin/bank/db/ConversionDAO.kt
+++ b/bank/src/main/kotlin/tech/libeufin/bank/db/ConversionDAO.kt
@@ -24,9 +24,7 @@ import tech.libeufin.bank.DecimalNumber
 import tech.libeufin.bank.RoundingMode
 import tech.libeufin.bank.internalServerError
 import tech.libeufin.common.TalerAmount
-import tech.libeufin.common.getAmount
-import tech.libeufin.common.oneOrNull
-import tech.libeufin.common.transaction
+import tech.libeufin.common.db.*
 
 /** Data access logic for conversion */
 class ConversionDAO(private val db: Database) {
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/db/Database.kt 
b/bank/src/main/kotlin/tech/libeufin/bank/db/Database.kt
index a37048c4..c843d355 100644
--- a/bank/src/main/kotlin/tech/libeufin/bank/db/Database.kt
+++ b/bank/src/main/kotlin/tech/libeufin/bank/db/Database.kt
@@ -28,6 +28,7 @@ import org.slf4j.Logger
 import org.slf4j.LoggerFactory
 import tech.libeufin.bank.*
 import tech.libeufin.common.*
+import tech.libeufin.common.db.*
 import java.sql.PreparedStatement
 import java.sql.ResultSet
 import java.sql.Types
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/db/ExchangeDAO.kt 
b/bank/src/main/kotlin/tech/libeufin/bank/db/ExchangeDAO.kt
index 69249f1a..c425c516 100644
--- a/bank/src/main/kotlin/tech/libeufin/bank/db/ExchangeDAO.kt
+++ b/bank/src/main/kotlin/tech/libeufin/bank/db/ExchangeDAO.kt
@@ -21,6 +21,7 @@ package tech.libeufin.bank.db
 
 import tech.libeufin.bank.*
 import tech.libeufin.common.*
+import tech.libeufin.common.db.*
 import java.time.Instant
 
 /** Data access logic for exchange specific logic */
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/db/GcDAO.kt 
b/bank/src/main/kotlin/tech/libeufin/bank/db/GcDAO.kt
index 7e1c7a08..29eede85 100644
--- a/bank/src/main/kotlin/tech/libeufin/bank/db/GcDAO.kt
+++ b/bank/src/main/kotlin/tech/libeufin/bank/db/GcDAO.kt
@@ -21,6 +21,7 @@ package tech.libeufin.bank.db
 
 import tech.libeufin.bank.*
 import tech.libeufin.common.*
+import tech.libeufin.common.db.*
 import tech.libeufin.common.crypto.*
 import java.time.Instant
 import java.time.Duration
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/db/NotificationWatcher.kt 
b/bank/src/main/kotlin/tech/libeufin/bank/db/NotificationWatcher.kt
index cd64e77f..077cb771 100644
--- a/bank/src/main/kotlin/tech/libeufin/bank/db/NotificationWatcher.kt
+++ b/bank/src/main/kotlin/tech/libeufin/bank/db/NotificationWatcher.kt
@@ -26,6 +26,7 @@ import org.slf4j.Logger
 import org.slf4j.LoggerFactory
 import tech.libeufin.bank.*
 import tech.libeufin.common.*
+import tech.libeufin.common.db.*
 import java.util.*
 import java.util.concurrent.ConcurrentHashMap
 
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/db/TanDAO.kt 
b/bank/src/main/kotlin/tech/libeufin/bank/db/TanDAO.kt
index c7328d65..fbc99960 100644
--- a/bank/src/main/kotlin/tech/libeufin/bank/db/TanDAO.kt
+++ b/bank/src/main/kotlin/tech/libeufin/bank/db/TanDAO.kt
@@ -22,8 +22,8 @@ package tech.libeufin.bank.db
 import tech.libeufin.bank.Operation
 import tech.libeufin.bank.TanChannel
 import tech.libeufin.bank.internalServerError
-import tech.libeufin.common.oneOrNull
 import tech.libeufin.common.micros
+import tech.libeufin.common.db.*
 import java.time.Duration
 import java.time.Instant
 import java.util.concurrent.TimeUnit
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/db/TokenDAO.kt 
b/bank/src/main/kotlin/tech/libeufin/bank/db/TokenDAO.kt
index ee1a1669..18a14c24 100644
--- a/bank/src/main/kotlin/tech/libeufin/bank/db/TokenDAO.kt
+++ b/bank/src/main/kotlin/tech/libeufin/bank/db/TokenDAO.kt
@@ -21,10 +21,9 @@ package tech.libeufin.bank.db
 
 import tech.libeufin.bank.BearerToken
 import tech.libeufin.bank.TokenScope
-import tech.libeufin.common.executeUpdateViolation
 import tech.libeufin.common.asInstant
-import tech.libeufin.common.oneOrNull
 import tech.libeufin.common.micros
+import tech.libeufin.common.db.*
 import java.time.Instant
 
 /** Data access logic for auth tokens */
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/db/TransactionDAO.kt 
b/bank/src/main/kotlin/tech/libeufin/bank/db/TransactionDAO.kt
index cf5ef9bc..7fb8823d 100644
--- a/bank/src/main/kotlin/tech/libeufin/bank/db/TransactionDAO.kt
+++ b/bank/src/main/kotlin/tech/libeufin/bank/db/TransactionDAO.kt
@@ -23,6 +23,7 @@ import org.slf4j.Logger
 import org.slf4j.LoggerFactory
 import tech.libeufin.bank.*
 import tech.libeufin.common.*
+import tech.libeufin.common.db.*
 import java.time.Instant
 
 private val logger: Logger = LoggerFactory.getLogger("libeufin-bank-tx-dao")
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/db/WithdrawalDAO.kt 
b/bank/src/main/kotlin/tech/libeufin/bank/db/WithdrawalDAO.kt
index 4b069339..9e27cb26 100644
--- a/bank/src/main/kotlin/tech/libeufin/bank/db/WithdrawalDAO.kt
+++ b/bank/src/main/kotlin/tech/libeufin/bank/db/WithdrawalDAO.kt
@@ -25,6 +25,7 @@ import kotlinx.coroutines.launch
 import kotlinx.coroutines.withTimeoutOrNull
 import tech.libeufin.bank.*
 import tech.libeufin.common.*
+import tech.libeufin.common.db.*
 import java.time.Instant
 import java.util.*
 
diff --git a/bank/src/test/kotlin/AmountTest.kt 
b/bank/src/test/kotlin/AmountTest.kt
index ccd64400..f89432b5 100644
--- a/bank/src/test/kotlin/AmountTest.kt
+++ b/bank/src/test/kotlin/AmountTest.kt
@@ -22,6 +22,7 @@ import tech.libeufin.bank.DecimalNumber
 import tech.libeufin.bank.db.TransactionDAO.BankTransactionResult
 import tech.libeufin.bank.db.WithdrawalDAO.WithdrawalCreationResult
 import tech.libeufin.common.*
+import tech.libeufin.common.db.*
 import java.time.Instant
 import java.util.*
 import kotlin.test.assertEquals
diff --git a/bank/src/test/kotlin/DatabaseTest.kt 
b/bank/src/test/kotlin/DatabaseTest.kt
index 70736d79..0536ae42 100644
--- a/bank/src/test/kotlin/DatabaseTest.kt
+++ b/bank/src/test/kotlin/DatabaseTest.kt
@@ -23,6 +23,7 @@ import org.junit.Test
 import tech.libeufin.bank.createAdminAccount
 import tech.libeufin.bank.db.AccountDAO.AccountCreationResult
 import tech.libeufin.common.*
+import tech.libeufin.common.db.*
 import java.time.Duration
 import java.time.Instant
 import java.time.temporal.ChronoUnit
diff --git a/bank/src/test/kotlin/GcTest.kt b/bank/src/test/kotlin/GcTest.kt
index 92c4bd41..32f78552 100644
--- a/bank/src/test/kotlin/GcTest.kt
+++ b/bank/src/test/kotlin/GcTest.kt
@@ -25,6 +25,7 @@ import tech.libeufin.bank.db.TransactionDAO.*
 import tech.libeufin.bank.db.CashoutDAO.CashoutCreationResult
 import tech.libeufin.bank.db.ExchangeDAO.TransferResult
 import tech.libeufin.common.*
+import tech.libeufin.common.db.*
 import io.ktor.client.request.*
 import io.ktor.client.statement.*
 import io.ktor.http.*
diff --git a/bank/src/test/kotlin/StatsTest.kt 
b/bank/src/test/kotlin/StatsTest.kt
index c34565fd..71f35d0a 100644
--- a/bank/src/test/kotlin/StatsTest.kt
+++ b/bank/src/test/kotlin/StatsTest.kt
@@ -23,6 +23,7 @@ import tech.libeufin.bank.MonitorResponse
 import tech.libeufin.bank.MonitorWithConversion
 import tech.libeufin.bank.Timeframe
 import tech.libeufin.common.*
+import tech.libeufin.common.db.*
 import java.time.Instant
 import java.time.LocalDateTime
 import kotlin.test.assertEquals
diff --git a/bank/src/test/kotlin/helpers.kt b/bank/src/test/kotlin/helpers.kt
index 0b29a0b0..06db3b8e 100644
--- a/bank/src/test/kotlin/helpers.kt
+++ b/bank/src/test/kotlin/helpers.kt
@@ -27,6 +27,7 @@ import tech.libeufin.bank.*
 import tech.libeufin.bank.db.AccountDAO.AccountCreationResult
 import tech.libeufin.bank.db.Database
 import tech.libeufin.common.*
+import tech.libeufin.common.db.*
 import java.nio.file.NoSuchFileException
 import kotlin.io.path.Path
 import kotlin.io.path.deleteExisting
diff --git a/common/build.gradle b/common/build.gradle
index 446910ec..cc9649af 100644
--- a/common/build.gradle
+++ b/common/build.gradle
@@ -28,4 +28,6 @@ dependencies {
     implementation("io.ktor:ktor-server-test-host:$ktor_version")
     implementation("org.jetbrains.kotlin:kotlin-test:$kotlin_version")
     implementation("com.github.ajalt.clikt:clikt:$clikt_version")
+
+    testImplementation("uk.org.webcompere:system-stubs-core:2.1.6")
 }
\ No newline at end of file
diff --git a/common/src/main/kotlin/DB.kt b/common/src/main/kotlin/DB.kt
deleted file mode 100644
index d2cb0a01..00000000
--- a/common/src/main/kotlin/DB.kt
+++ /dev/null
@@ -1,355 +0,0 @@
-/*
- * This file is part of LibEuFin.
- * Copyright (C) 2023 Taler Systems S.A.
- *
- * LibEuFin is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation; either version 3, or
- * (at your option) any later version.
- *
- * LibEuFin is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General
- * Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public
- * License along with LibEuFin; see the file COPYING.  If not, see
- * <http://www.gnu.org/licenses/>
- */
-
-package tech.libeufin.common
-
-import com.zaxxer.hikari.HikariConfig
-import com.zaxxer.hikari.HikariDataSource
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.withContext
-import org.postgresql.ds.PGSimpleDataSource
-import org.postgresql.jdbc.PgConnection
-import org.postgresql.util.PSQLState
-import org.slf4j.Logger
-import org.slf4j.LoggerFactory
-import java.net.URI
-import java.nio.file.Path
-import java.sql.PreparedStatement
-import java.sql.ResultSet
-import java.sql.SQLException
-import kotlin.io.path.Path
-import kotlin.io.path.exists
-import kotlin.io.path.readText
-
-fun getCurrentUser(): String = System.getProperty("user.name")
-
-private val logger: Logger = LoggerFactory.getLogger("libeufin-db")
-
-// Check GANA (https://docs.gnunet.org/gana/index.html) for numbers allowance.
-
-/**
- * This function converts postgresql:// URIs to JDBC URIs.
- *
- * URIs that are already jdbc: URIs are passed through.
- *
- * This avoids the user having to create complex JDBC URIs for postgres 
connections.
- * They are especially complex when using unix domain sockets, as they're not 
really
- * supported natively by JDBC.
- */
-fun getJdbcConnectionFromPg(pgConn: String): String {
-    // Pass through jdbc URIs.
-    if (pgConn.startsWith("jdbc:")) {
-        return pgConn
-    }
-    if (!pgConn.startsWith("postgresql://") && 
!pgConn.startsWith("postgres://")) {
-        throw Exception("Not a Postgres connection string: $pgConn")
-    }
-    var maybeUnixSocket = false
-    val parsed = URI(pgConn)
-    var hostAsParam: String? = if (parsed.query != null) {
-        getQueryParam(parsed.query, "host")
-    } else {
-        null
-    }
-    var pgHost = System.getenv("PGHOST")
-    if (null == pgHost)
-      pgHost = parsed.host
-    var pgPort = System.getenv("PGPORT")
-    if (null == pgPort) {
-      if (-1 == parsed.port)
-        pgPort = "5432"
-      else
-        pgPort = parsed.port.toString()
-    }
-
-    /**
-     * In some cases, it is possible to leave the hostname empty
-     * and specify it via a query param, therefore a "postgresql:///"-starting
-     * connection string does NOT always mean Unix domain socket.
-     * 
https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING
-     */
-    if (pgHost == null &&
-        (hostAsParam == null || hostAsParam.startsWith('/'))
-    ) {
-        maybeUnixSocket = true
-    }
-    if (pgHost != null &&
-        (pgHost.startsWith('/'))
-    ) {
-        maybeUnixSocket = true
-    }
-    if (maybeUnixSocket) {
-        // Check whether the database user should differ from the process user.
-        var pgUser = getCurrentUser()
-        if (parsed.query != null) {
-            val maybeUserParam = getQueryParam(parsed.query, "user")
-            if (maybeUserParam != null) pgUser = maybeUserParam
-        }
-        // Check whether the Unix domain socket location was given 
non-standard.
-        if ( (null == hostAsParam) && (null != pgHost) )
-          hostAsParam = pgHost + "/.s.PGSQL." + pgPort
-        val socketLocation = hostAsParam ?: "/var/run/postgresql/.s.PGSQL." + 
pgPort
-        if (!socketLocation.startsWith('/')) {
-            throw Exception("PG connection wants Unix domain socket, but 
non-null host doesn't start with slash")
-        }
-        return 
"jdbc:postgresql://localhost${parsed.path}?user=$pgUser&socketFactory=org.newsclub.net.unix."
 +
-                
"AFUNIXSocketFactory\$FactoryArg&socketFactoryArg=$socketLocation"
-    }
-    if (pgConn.startsWith("postgres://")) {
-        // The JDBC driver doesn't like postgres://, only postgresql://.
-        // For consistency with other components, we normalize the postgres:// 
URI
-        // into one that the JDBC driver likes.
-        return "jdbc:postgresql://" + pgConn.removePrefix("postgres://")
-    }
-    logger.info("connecting to database via JDBC string '$pgConn'")
-    return "jdbc:$pgConn"
-}
-
-data class DatabaseConfig(
-    val dbConnStr: String,
-    val sqlDir: Path
-)
-
-fun pgDataSource(dbConfig: String): PGSimpleDataSource {
-    val jdbcConnStr = getJdbcConnectionFromPg(dbConfig)
-    logger.debug("connecting to database via JDBC string '$jdbcConnStr'")
-    val pgSource = PGSimpleDataSource()
-    pgSource.setUrl(jdbcConnStr)
-    pgSource.prepareThreshold = 1
-    return pgSource
-}
-
-fun PGSimpleDataSource.pgConnection(schema: String? = null): PgConnection {
-    val conn = connection.unwrap(PgConnection::class.java)
-    if (schema != null) conn.execSQLUpdate("SET search_path TO $schema")
-    return conn
-}
-
-fun <R> PgConnection.transaction(lambda: (PgConnection) -> R): R {
-    try {
-        autoCommit = false
-        val result = lambda(this)
-        commit()
-        autoCommit = true
-        return result
-    } catch (e: Exception) {
-        rollback()
-        autoCommit = true
-        throw e
-    }
-}
-
-fun <T> PreparedStatement.oneOrNull(lambda: (ResultSet) -> T): T? {
-    executeQuery().use {
-        return if (it.next()) lambda(it) else null
-    }
-}
-
-fun <T> PreparedStatement.one(lambda: (ResultSet) -> T): T =
-    requireNotNull(oneOrNull(lambda)) { "Missing result to database query" }
-
-fun <T> PreparedStatement.all(lambda: (ResultSet) -> T): List<T> {
-    executeQuery().use {
-        val ret = mutableListOf<T>()
-        while (it.next()) {
-            ret.add(lambda(it))
-        }
-        return ret
-    }
-}
-
-fun PreparedStatement.executeQueryCheck(): Boolean {
-    executeQuery().use {
-        return it.next()
-    }
-}
-
-fun PreparedStatement.executeUpdateCheck(): Boolean {
-    executeUpdate()
-    return updateCount > 0
-}
-
-/**
- * Helper that returns false if the row to be inserted
- * hits a unique key constraint violation, true when it
- * succeeds.  Any other error (re)throws exception.
- */
-fun PreparedStatement.executeUpdateViolation(): Boolean {
-    return try {
-        executeUpdateCheck()
-    } catch (e: SQLException) {
-        logger.debug(e.message)
-        if (e.sqlState == PSQLState.UNIQUE_VIOLATION.state) return false
-        throw e // rethrowing, not to hide other types of errors.
-    }
-}
-
-fun PreparedStatement.executeProcedureViolation(): Boolean {
-    val savepoint = connection.setSavepoint()
-    return try {
-        executeUpdate()
-        connection.releaseSavepoint(savepoint)
-        true
-    } catch (e: SQLException) {
-        connection.rollback(savepoint)
-        if (e.sqlState == PSQLState.UNIQUE_VIOLATION.state) return false
-        throw e // rethrowing, not to hide other types of errors.
-    }
-}
-
-// TODO comment
-fun PgConnection.dynamicUpdate(
-    table: String,
-    fields: Sequence<String>,
-    filter: String,
-    bind: Sequence<Any?>,
-) {
-    val sql = fields.joinToString()
-    if (sql.isEmpty()) return
-    prepareStatement("UPDATE $table SET $sql $filter").run {
-        for ((idx, value) in bind.withIndex()) {
-            setObject(idx + 1, value)
-        }
-        executeUpdate()
-    }
-}
-
-/**
- * Only runs versioning.sql if the _v schema is not found.
- *
- * @param conn database connection
- * @param cfg database configuration
- */
-fun maybeApplyV(conn: PgConnection, cfg: DatabaseConfig) {
-    conn.transaction {
-        val checkVSchema = conn.prepareStatement(
-            "SELECT schema_name FROM information_schema.schemata WHERE 
schema_name = '_v'"
-        )
-        if (!checkVSchema.executeQueryCheck()) {
-            logger.debug("_v schema not found, applying versioning.sql")
-            val sqlVersioning = Path("${cfg.sqlDir}/versioning.sql").readText()
-            conn.execSQLUpdate(sqlVersioning)
-        }
-    }
-}
-
-// sqlFilePrefix is, for example, "libeufin-bank" or "libeufin-nexus" (no 
trailing dash).
-fun initializeDatabaseTables(conn: PgConnection, cfg: DatabaseConfig, 
sqlFilePrefix: String) {
-    logger.info("doing DB initialization, sqldir ${cfg.sqlDir}")
-    maybeApplyV(conn, cfg)
-    conn.transaction {
-        val checkStmt = conn.prepareStatement("SELECT count(*) as n FROM 
_v.patches where patch_name = ?")
-
-        for (n in 1..9999) {
-            val numStr = n.toString().padStart(4, '0')
-            val patchName = "$sqlFilePrefix-$numStr"
-
-            checkStmt.setString(1, patchName)
-            val patchCount = checkStmt.oneOrNull { it.getInt(1) } ?: throw 
Exception("unable to query patches")
-            if (patchCount >= 1) {
-                logger.debug("patch $patchName already applied")
-                continue
-            }
-
-            val path = Path("${cfg.sqlDir}/$sqlFilePrefix-$numStr.sql")
-            if (!path.exists()) {
-                logger.debug("path $path doesn't exist anymore, stopping")
-                break
-            }
-            logger.info("applying patch $path")
-            val sqlPatchText = path.readText()
-            conn.execSQLUpdate(sqlPatchText)
-        }
-        val sqlProcedures = Path("${cfg.sqlDir}/$sqlFilePrefix-procedures.sql")
-        if (!sqlProcedures.exists()) {
-            logger.warn("no procedures.sql for the SQL collection: 
$sqlFilePrefix")
-            return@transaction
-        }
-        logger.info("run procedure.sql")
-        conn.execSQLUpdate(sqlProcedures.readText())
-    }
-}
-
-// sqlFilePrefix is, for example, "libeufin-bank" or "libeufin-nexus" (no 
trailing dash).
-fun resetDatabaseTables(conn: PgConnection, cfg: DatabaseConfig, 
sqlFilePrefix: String) {
-    logger.info("reset DB, sqldir ${cfg.sqlDir}")
-    val sqlDrop = Path("${cfg.sqlDir}/$sqlFilePrefix-drop.sql").readText()
-    conn.execSQLUpdate(sqlDrop)
-}
-
-open class DbPool(cfg: String, schema: String) : java.io.Closeable {
-    val pgSource = pgDataSource(cfg)
-    private val pool: HikariDataSource
-
-    init {
-        val config = HikariConfig()
-        config.dataSource = pgSource
-        config.schema = schema
-        config.transactionIsolation = "TRANSACTION_SERIALIZABLE"
-        pool = HikariDataSource(config)
-        pool.connection.use { con ->
-            val meta = con.metaData
-            val majorVersion = meta.databaseMajorVersion
-            val minorVersion = meta.databaseMinorVersion
-            if (majorVersion < MIN_VERSION) {
-                throw Exception("postgres version must be at least 
$MIN_VERSION.0 got $majorVersion.$minorVersion")
-            }
-        }
-    }
-
-    suspend fun <R> conn(lambda: suspend (PgConnection) -> R): R {
-        // Use a coroutine dispatcher that we can block as JDBC API is blocking
-        return withContext(Dispatchers.IO) {
-            pool.connection.use { lambda(it.unwrap(PgConnection::class.java)) }
-        }
-    }
-
-    suspend fun <R> serializable(lambda: suspend (PgConnection) -> R): R = 
conn { conn ->
-        repeat(SERIALIZATION_RETRY) {
-            try {
-                return@conn lambda(conn)
-            } catch (e: SQLException) {
-                if (e.sqlState != PSQLState.SERIALIZATION_FAILURE.state)
-                    throw e
-            }
-        }
-        try {
-            return@conn lambda(conn)
-        } catch (e: SQLException) {
-            logger.warn("Serialization failure after $SERIALIZATION_RETRY 
retry")
-            throw e
-        }
-    }
-
-    override fun close() {
-        pool.close()
-    }
-}
-
-fun ResultSet.getAmount(name: String, currency: String): TalerAmount {
-    return TalerAmount(
-        getLong("${name}_val"),
-        getInt("${name}_frac"),
-        currency
-    )
-}
-
-fun ResultSet.getBankPayto(payto: String, name: String, ctx: BankPaytoCtx): 
String {
-    return Payto.parse(getString(payto)).bank(getString(name), ctx)
-}
\ No newline at end of file
diff --git a/common/src/main/kotlin/db/DbPool.kt 
b/common/src/main/kotlin/db/DbPool.kt
new file mode 100644
index 00000000..4b6944cc
--- /dev/null
+++ b/common/src/main/kotlin/db/DbPool.kt
@@ -0,0 +1,78 @@
+/*
+ * This file is part of LibEuFin.
+ * Copyright (C) 2024 Taler Systems S.A.
+ *
+ * LibEuFin is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3, or
+ * (at your option) any later version.
+ *
+ * LibEuFin is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General
+ * Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with LibEuFin; see the file COPYING.  If not, see
+ * <http://www.gnu.org/licenses/>
+ */
+
+package tech.libeufin.common.db
+
+import tech.libeufin.common.*
+import org.postgresql.jdbc.PgConnection
+import org.postgresql.util.PSQLState
+import java.sql.SQLException
+import com.zaxxer.hikari.HikariConfig
+import com.zaxxer.hikari.HikariDataSource
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.withContext
+
+open class DbPool(cfg: String, schema: String) : java.io.Closeable {
+    val pgSource = pgDataSource(cfg)
+    private val pool: HikariDataSource
+
+    init {
+        val config = HikariConfig()
+        config.dataSource = pgSource
+        config.schema = schema
+        config.transactionIsolation = "TRANSACTION_SERIALIZABLE"
+        pool = HikariDataSource(config)
+        pool.connection.use { con ->
+            val meta = con.metaData
+            val majorVersion = meta.databaseMajorVersion
+            val minorVersion = meta.databaseMinorVersion
+            if (majorVersion < MIN_VERSION) {
+                throw Exception("postgres version must be at least 
$MIN_VERSION.0 got $majorVersion.$minorVersion")
+            }
+        }
+    }
+
+    suspend fun <R> conn(lambda: suspend (PgConnection) -> R): R {
+        // Use a coroutine dispatcher that we can block as JDBC API is blocking
+        return withContext(Dispatchers.IO) {
+            pool.connection.use { lambda(it.unwrap(PgConnection::class.java)) }
+        }
+    }
+
+    suspend fun <R> serializable(lambda: suspend (PgConnection) -> R): R = 
conn { conn ->
+        repeat(SERIALIZATION_RETRY) {
+            try {
+                return@conn lambda(conn)
+            } catch (e: SQLException) {
+                if (e.sqlState != PSQLState.SERIALIZATION_FAILURE.state)
+                    throw e
+            }
+        }
+        try {
+            return@conn lambda(conn)
+        } catch (e: SQLException) {
+            logger.warn("Serialization failure after $SERIALIZATION_RETRY 
retry")
+            throw e
+        }
+    }
+
+    override fun close() {
+        pool.close()
+    }
+}
\ No newline at end of file
diff --git a/common/src/main/kotlin/db/config.kt 
b/common/src/main/kotlin/db/config.kt
new file mode 100644
index 00000000..6f225f05
--- /dev/null
+++ b/common/src/main/kotlin/db/config.kt
@@ -0,0 +1,95 @@
+/*
+ * This file is part of LibEuFin.
+ * Copyright (C) 2024 Taler Systems S.A.
+ *
+ * LibEuFin is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3, or
+ * (at your option) any later version.
+ *
+ * LibEuFin is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General
+ * Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with LibEuFin; see the file COPYING.  If not, see
+ * <http://www.gnu.org/licenses/>
+ */
+
+package tech.libeufin.common.db
+
+import tech.libeufin.common.*
+import org.postgresql.ds.PGSimpleDataSource
+import org.postgresql.jdbc.PgConnection
+import org.postgresql.util.PSQLState
+import org.slf4j.Logger
+import org.slf4j.LoggerFactory
+import io.ktor.http.parseQueryString
+import java.net.URI
+import java.nio.file.Path
+import java.sql.PreparedStatement
+import java.sql.ResultSet
+import java.sql.SQLException
+import kotlin.io.path.Path
+
+fun currentUser(): String = System.getProperty("user.name")
+
+/**
+ * This function converts postgresql:// URIs to JDBC URIs.
+ *
+ * URIs that are already jdbc: URIs are passed through.
+ *
+ * This avoids the user having to create complex JDBC URIs for postgres 
connections.
+ * They are especially complex when using unix domain sockets, as they're not 
really
+ * supported natively by JDBC.
+ */
+fun jdbcFromPg(pgConn: String): String {
+    // Pass through jdbc URIs.
+    if (pgConn.startsWith("jdbc:")) {
+        return pgConn
+    }
+    if (!pgConn.startsWith("postgresql://") && 
!pgConn.startsWith("postgres://")) {
+        throw Exception("Not a Postgres connection string: $pgConn")
+    }
+    var maybeUnixSocket = false
+    val uri = URI(pgConn)
+    val params = parseQueryString(uri.query ?: "", decode = false)
+
+    val host = uri.host ?: params["host"] ?: System.getenv("PGHOST")
+    if (host == null || host.startsWith('/')) {
+        val port = (if (uri.port == -1) null else uri.port.toString()) ?: 
params["port"] ?: System.getenv("PGPORT") ?: "5432"
+        val user = params["user"] ?: currentUser()
+        val unixPath = (host ?:"/var/run/postgresql") + "/.s.PGSQL.$port"
+        return 
"jdbc:postgresql://localhost${uri.path}?user=$user&socketFactory=org.newsclub.net.unix."
 +
+                "AFUNIXSocketFactory\$FactoryArg&socketFactoryArg=$unixPath"
+    }
+    if (pgConn.startsWith("postgres://")) {
+        // The JDBC driver doesn't like postgres://, only postgresql://.
+        // For consistency with other components, we normalize the postgres:// 
URI
+        // into one that the JDBC driver likes.
+        return "jdbc:postgresql://" + pgConn.removePrefix("postgres://")
+    }
+    logger.info("connecting to database via JDBC string '$pgConn'")
+    return "jdbc:$pgConn"
+}
+
+data class DatabaseConfig(
+    val dbConnStr: String,
+    val sqlDir: Path
+)
+
+fun pgDataSource(dbConfig: String): PGSimpleDataSource {
+    val jdbcConnStr = jdbcFromPg(dbConfig)
+    logger.debug("connecting to database via JDBC string '$jdbcConnStr'")
+    val pgSource = PGSimpleDataSource()
+    pgSource.setUrl(jdbcConnStr)
+    pgSource.prepareThreshold = 1
+    return pgSource
+}
+
+fun PGSimpleDataSource.pgConnection(schema: String? = null): PgConnection {
+    val conn = connection.unwrap(PgConnection::class.java)
+    if (schema != null) conn.execSQLUpdate("SET search_path TO $schema")
+    return conn
+}
diff --git a/common/src/main/kotlin/db/schema.kt 
b/common/src/main/kotlin/db/schema.kt
new file mode 100644
index 00000000..af589cbb
--- /dev/null
+++ b/common/src/main/kotlin/db/schema.kt
@@ -0,0 +1,89 @@
+/*
+ * This file is part of LibEuFin.
+ * Copyright (C) 2024 Taler Systems S.A.
+ *
+ * LibEuFin is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3, or
+ * (at your option) any later version.
+ *
+ * LibEuFin is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General
+ * Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with LibEuFin; see the file COPYING.  If not, see
+ * <http://www.gnu.org/licenses/>
+ */
+
+package tech.libeufin.common.db
+
+import tech.libeufin.common.*
+import org.postgresql.jdbc.PgConnection
+import kotlin.io.path.Path
+import kotlin.io.path.exists
+import kotlin.io.path.readText
+
+/**
+ * Only runs versioning.sql if the _v schema is not found.
+ *
+ * @param conn database connection
+ * @param cfg database configuration
+ */
+fun maybeApplyV(conn: PgConnection, cfg: DatabaseConfig) {
+    conn.transaction {
+        val checkVSchema = conn.prepareStatement(
+            "SELECT schema_name FROM information_schema.schemata WHERE 
schema_name = '_v'"
+        )
+        if (!checkVSchema.executeQueryCheck()) {
+            logger.debug("_v schema not found, applying versioning.sql")
+            val sqlVersioning = Path("${cfg.sqlDir}/versioning.sql").readText()
+            conn.execSQLUpdate(sqlVersioning)
+        }
+    }
+}
+
+// sqlFilePrefix is, for example, "libeufin-bank" or "libeufin-nexus" (no 
trailing dash).
+fun initializeDatabaseTables(conn: PgConnection, cfg: DatabaseConfig, 
sqlFilePrefix: String) {
+    logger.info("doing DB initialization, sqldir ${cfg.sqlDir}")
+    maybeApplyV(conn, cfg)
+    conn.transaction {
+        val checkStmt = conn.prepareStatement("SELECT count(*) as n FROM 
_v.patches where patch_name = ?")
+
+        for (n in 1..9999) {
+            val numStr = n.toString().padStart(4, '0')
+            val patchName = "$sqlFilePrefix-$numStr"
+
+            checkStmt.setString(1, patchName)
+            val patchCount = checkStmt.oneOrNull { it.getInt(1) } ?: throw 
Exception("unable to query patches")
+            if (patchCount >= 1) {
+                logger.debug("patch $patchName already applied")
+                continue
+            }
+
+            val path = Path("${cfg.sqlDir}/$sqlFilePrefix-$numStr.sql")
+            if (!path.exists()) {
+                logger.debug("path $path doesn't exist anymore, stopping")
+                break
+            }
+            logger.info("applying patch $path")
+            val sqlPatchText = path.readText()
+            conn.execSQLUpdate(sqlPatchText)
+        }
+        val sqlProcedures = Path("${cfg.sqlDir}/$sqlFilePrefix-procedures.sql")
+        if (!sqlProcedures.exists()) {
+            logger.warn("no procedures.sql for the SQL collection: 
$sqlFilePrefix")
+            return@transaction
+        }
+        logger.info("run procedure.sql")
+        conn.execSQLUpdate(sqlProcedures.readText())
+    }
+}
+
+// sqlFilePrefix is, for example, "libeufin-bank" or "libeufin-nexus" (no 
trailing dash).
+fun resetDatabaseTables(conn: PgConnection, cfg: DatabaseConfig, 
sqlFilePrefix: String) {
+    logger.info("reset DB, sqldir ${cfg.sqlDir}")
+    val sqlDrop = Path("${cfg.sqlDir}/$sqlFilePrefix-drop.sql").readText()
+    conn.execSQLUpdate(sqlDrop)
+}
\ No newline at end of file
diff --git a/common/src/main/kotlin/iban.kt b/common/src/main/kotlin/db/types.kt
similarity index 63%
copy from common/src/main/kotlin/iban.kt
copy to common/src/main/kotlin/db/types.kt
index 328e7f82..cafc30c2 100644
--- a/common/src/main/kotlin/iban.kt
+++ b/common/src/main/kotlin/db/types.kt
@@ -1,34 +1,35 @@
 /*
  * This file is part of LibEuFin.
  * Copyright (C) 2024 Taler Systems S.A.
-
+ *
  * LibEuFin is free software; you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as
  * published by the Free Software Foundation; either version 3, or
  * (at your option) any later version.
-
+ *
  * LibEuFin is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General
  * Public License for more details.
-
+ *
  * You should have received a copy of the GNU Affero General Public
  * License along with LibEuFin; see the file COPYING.  If not, see
  * <http://www.gnu.org/licenses/>
  */
 
-package tech.libeufin.common
+package tech.libeufin.common.db
 
-// Taken from the ISO20022 XSD schema
-private val bicRegex = Regex("^[A-Z]{6}[A-Z2-9][A-NP-Z0-9]([A-Z0-9]{3})?$")
+import tech.libeufin.common.*
+import java.sql.ResultSet
 
-fun validateBic(bic: String): Boolean {
-    return bicRegex.matches(bic)
+fun ResultSet.getAmount(name: String, currency: String): TalerAmount {
+    return TalerAmount(
+        getLong("${name}_val"),
+        getInt("${name}_frac"),
+        currency
+    )
 }
 
-// Taken from the ISO20022 XSD schema
-private val ibanRegex = Regex("^[A-Z]{2}[0-9]{2}[a-zA-Z0-9]{1,30}$")
-
-fun validateIban(iban: String): Boolean {
-    return ibanRegex.matches(iban)
+fun ResultSet.getBankPayto(payto: String, name: String, ctx: BankPaytoCtx): 
String {
+    return Payto.parse(getString(payto)).bank(getString(name), ctx)
 }
\ No newline at end of file
diff --git a/common/src/main/kotlin/db/utils.kt 
b/common/src/main/kotlin/db/utils.kt
new file mode 100644
index 00000000..d1197894
--- /dev/null
+++ b/common/src/main/kotlin/db/utils.kt
@@ -0,0 +1,124 @@
+/*
+ * This file is part of LibEuFin.
+ * Copyright (C) 2024 Taler Systems S.A.
+ *
+ * LibEuFin is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3, or
+ * (at your option) any later version.
+ *
+ * LibEuFin is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General
+ * Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with LibEuFin; see the file COPYING.  If not, see
+ * <http://www.gnu.org/licenses/>
+ */
+
+package tech.libeufin.common.db
+
+import tech.libeufin.common.*
+import org.postgresql.ds.PGSimpleDataSource
+import org.postgresql.jdbc.PgConnection
+import org.postgresql.util.PSQLState
+import org.slf4j.Logger
+import org.slf4j.LoggerFactory
+import java.net.URI
+import java.nio.file.Path
+import java.sql.PreparedStatement
+import java.sql.ResultSet
+import java.sql.SQLException
+import kotlin.io.path.Path
+
+internal val logger: Logger = LoggerFactory.getLogger("libeufin-db")
+
+fun <R> PgConnection.transaction(lambda: (PgConnection) -> R): R {
+    try {
+        autoCommit = false
+        val result = lambda(this)
+        commit()
+        autoCommit = true
+        return result
+    } catch (e: Exception) {
+        rollback()
+        autoCommit = true
+        throw e
+    }
+}
+
+fun <T> PreparedStatement.oneOrNull(lambda: (ResultSet) -> T): T? {
+    executeQuery().use {
+        return if (it.next()) lambda(it) else null
+    }
+}
+
+fun <T> PreparedStatement.one(lambda: (ResultSet) -> T): T =
+    requireNotNull(oneOrNull(lambda)) { "Missing result to database query" }
+
+fun <T> PreparedStatement.all(lambda: (ResultSet) -> T): List<T> {
+    executeQuery().use {
+        val ret = mutableListOf<T>()
+        while (it.next()) {
+            ret.add(lambda(it))
+        }
+        return ret
+    }
+}
+
+fun PreparedStatement.executeQueryCheck(): Boolean {
+    executeQuery().use {
+        return it.next()
+    }
+}
+
+fun PreparedStatement.executeUpdateCheck(): Boolean {
+    executeUpdate()
+    return updateCount > 0
+}
+
+/**
+ * Helper that returns false if the row to be inserted
+ * hits a unique key constraint violation, true when it
+ * succeeds.  Any other error (re)throws exception.
+ */
+fun PreparedStatement.executeUpdateViolation(): Boolean {
+    return try {
+        executeUpdateCheck()
+    } catch (e: SQLException) {
+        logger.debug(e.message)
+        if (e.sqlState == PSQLState.UNIQUE_VIOLATION.state) return false
+        throw e // rethrowing, not to hide other types of errors.
+    }
+}
+
+fun PreparedStatement.executeProcedureViolation(): Boolean {
+    val savepoint = connection.setSavepoint()
+    return try {
+        executeUpdate()
+        connection.releaseSavepoint(savepoint)
+        true
+    } catch (e: SQLException) {
+        connection.rollback(savepoint)
+        if (e.sqlState == PSQLState.UNIQUE_VIOLATION.state) return false
+        throw e // rethrowing, not to hide other types of errors.
+    }
+}
+
+// TODO comment
+fun PgConnection.dynamicUpdate(
+    table: String,
+    fields: Sequence<String>,
+    filter: String,
+    bind: Sequence<Any?>,
+) {
+    val sql = fields.joinToString()
+    if (sql.isEmpty()) return
+    prepareStatement("UPDATE $table SET $sql $filter").run {
+        for ((idx, value) in bind.withIndex()) {
+            setObject(idx + 1, value)
+        }
+        executeUpdate()
+    }
+}
\ No newline at end of file
diff --git a/common/src/test/kotlin/ConfigTest.kt 
b/common/src/test/kotlin/ConfigTest.kt
index cb573501..1450c18e 100644
--- a/common/src/test/kotlin/ConfigTest.kt
+++ b/common/src/test/kotlin/ConfigTest.kt
@@ -18,8 +18,10 @@
  */
 
 import org.junit.Test
+import uk.org.webcompere.systemstubs.SystemStubs.*
 import java.time.Duration
 import tech.libeufin.common.*
+import tech.libeufin.common.db.*
 import kotlin.test.*
 
 class ConfigTest {
@@ -44,4 +46,19 @@ class ConfigTest {
         )
         assertEquals(parseTime("1h10m12s"), parseTime("1h10'12\""))
     }
+
+    @Test
+    fun jdbcParsing() {
+        val user = currentUser()
+        assertFails { jdbcFromPg("test") }
+        assertEquals("jdbc:test", jdbcFromPg("jdbc:test"))
+        
assertEquals("jdbc:postgresql://localhost/?user=$user&socketFactory=org.newsclub.net.unix.AFUNIXSocketFactory\$FactoryArg&socketFactoryArg=/var/run/postgresql/.s.PGSQL.5432",
 jdbcFromPg("postgresql:///"))
+        
assertEquals("jdbc:postgresql://?host=args%2Dhost&user=arg%23%24User&password=%21%22%23%24%25%26%27%28%29",
 
jdbcFromPg("postgresql://?host=args%2Dhost&user=arg%23%24User&password=%21%22%23%24%25%26%27%28%29"))
+        withEnvironmentVariable("PGPORT", "1234").execute {
+            
assertEquals("jdbc:postgresql://localhost/?user=$user&socketFactory=org.newsclub.net.unix.AFUNIXSocketFactory\$FactoryArg&socketFactoryArg=/var/run/postgresql/.s.PGSQL.1234",
 jdbcFromPg("postgresql:///"))
+        }
+        withEnvironmentVariable("PGPORT", "1234").and("PGHOST", 
"/tmp").execute {
+            
assertEquals("jdbc:postgresql://localhost/?user=antoine&socketFactory=org.newsclub.net.unix.AFUNIXSocketFactory\$FactoryArg&socketFactoryArg=/tmp/.s.PGSQL.1234",
 jdbcFromPg("postgresql:///"))
+        }
+    }
 }
\ No newline at end of file
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/DbInit.kt 
b/nexus/src/main/kotlin/tech/libeufin/nexus/DbInit.kt
index 73bdf4fb..7120faf2 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/DbInit.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/DbInit.kt
@@ -23,6 +23,7 @@ import 
com.github.ajalt.clikt.parameters.groups.provideDelegate
 import com.github.ajalt.clikt.parameters.options.flag
 import com.github.ajalt.clikt.parameters.options.option
 import tech.libeufin.common.*
+import tech.libeufin.common.db.*
 
 /**
  * This subcommand tries to load the SQL files that define
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt 
b/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt
index 4cc67eec..72f64f58 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt
@@ -36,6 +36,7 @@ import kotlinx.coroutines.*
 import org.slf4j.Logger
 import org.slf4j.LoggerFactory
 import tech.libeufin.common.*
+import tech.libeufin.common.db.*
 import tech.libeufin.nexus.ebics.*
 import tech.libeufin.nexus.db.*
 import java.nio.file.Path
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/db/Database.kt 
b/nexus/src/main/kotlin/tech/libeufin/nexus/db/Database.kt
index 2827b5f3..069185a9 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/db/Database.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/db/Database.kt
@@ -20,6 +20,7 @@ package tech.libeufin.nexus.db
 
 import org.postgresql.util.PSQLState
 import tech.libeufin.common.*
+import tech.libeufin.common.db.*
 import tech.libeufin.nexus.*
 import java.sql.PreparedStatement
 import java.sql.SQLException
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/db/InitiatedDAO.kt 
b/nexus/src/main/kotlin/tech/libeufin/nexus/db/InitiatedDAO.kt
index 162fddee..ac27f04b 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/db/InitiatedDAO.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/db/InitiatedDAO.kt
@@ -21,6 +21,7 @@ package tech.libeufin.nexus.db
 
 import tech.libeufin.nexus.*
 import tech.libeufin.common.*
+import tech.libeufin.common.db.*
 import java.time.Instant
 import java.sql.ResultSet
 
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/db/PaymentDAO.kt 
b/nexus/src/main/kotlin/tech/libeufin/nexus/db/PaymentDAO.kt
index 2730a437..8aa7cd2d 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/db/PaymentDAO.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/db/PaymentDAO.kt
@@ -21,6 +21,7 @@ package tech.libeufin.nexus.db
 
 import tech.libeufin.nexus.*
 import tech.libeufin.common.*
+import tech.libeufin.common.db.*
 import java.time.Instant
 
 /** Data access logic for incoming & outgoing payments */
diff --git a/nexus/src/test/kotlin/helpers.kt b/nexus/src/test/kotlin/helpers.kt
index 61aed19d..f0c0f8f7 100644
--- a/nexus/src/test/kotlin/helpers.kt
+++ b/nexus/src/test/kotlin/helpers.kt
@@ -22,6 +22,7 @@ import io.ktor.client.engine.mock.*
 import io.ktor.client.request.*
 import kotlinx.coroutines.runBlocking
 import tech.libeufin.common.*
+import tech.libeufin.common.db.*
 import tech.libeufin.nexus.*
 import tech.libeufin.nexus.db.*
 import java.time.Instant
diff --git a/testbench/src/test/kotlin/IntegrationTest.kt 
b/testbench/src/test/kotlin/IntegrationTest.kt
index 441ec143..b690462b 100644
--- a/testbench/src/test/kotlin/IntegrationTest.kt
+++ b/testbench/src/test/kotlin/IntegrationTest.kt
@@ -23,6 +23,7 @@ import tech.libeufin.nexus.*
 import tech.libeufin.nexus.db.Database as NexusDb
 import tech.libeufin.bank.db.AccountDAO.*
 import tech.libeufin.common.*
+import tech.libeufin.common.db.*
 import java.time.Instant
 import java.util.Arrays
 import java.sql.SQLException
diff --git a/testbench/src/test/kotlin/MigrationTest.kt 
b/testbench/src/test/kotlin/MigrationTest.kt
index 9b93557a..25b72605 100644
--- a/testbench/src/test/kotlin/MigrationTest.kt
+++ b/testbench/src/test/kotlin/MigrationTest.kt
@@ -23,6 +23,7 @@ import 
tech.libeufin.bank.db.WithdrawalDAO.WithdrawalCreationResult
 import tech.libeufin.bank.db.*
 import tech.libeufin.bank.*
 import tech.libeufin.common.*
+import tech.libeufin.common.db.*
 import java.time.Instant
 import java.util.*
 import org.postgresql.jdbc.PgConnection

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]