84 lines
3.1 KiB
Nim
84 lines
3.1 KiB
Nim
# SPDX-FileCopyrightText: ☭ Emery Hemingway
|
|
# SPDX-License-Identifier: Unlicense
|
|
|
|
|
|
import preserves, syndicate, syndicate/relays
|
|
import ../schema/[config, sql]
|
|
|
|
{.passL: "-lpq".}
|
|
|
|
{.pragma: libpq, header: "libpq-fe.h", importc.}
|
|
|
|
type
|
|
PGconn* {.libpq.} = ptr object
|
|
ConnStatusType* {.libpq.} = enum
|
|
CONNECTION_OK, CONNECTION_BAD, ## Non-blocking mode only below here
|
|
##
|
|
## The existence of these should never be relied upon - they should only
|
|
## be used for user feedback or similar purposes.
|
|
##
|
|
CONNECTION_STARTED, ## Waiting for connection to be made.
|
|
CONNECTION_MADE, ## Connection OK; waiting to send.
|
|
CONNECTION_AWAITING_RESPONSE, ## Waiting for a response from the
|
|
## postmaster.
|
|
CONNECTION_AUTH_OK, ## Received authentication; waiting for
|
|
## backend startup.
|
|
CONNECTION_SETENV, ## This state is no longer used.
|
|
CONNECTION_SSL_STARTUP, ## Negotiating SSL.
|
|
CONNECTION_NEEDED, ## Internal state: connect() needed
|
|
CONNECTION_CHECK_WRITABLE, ## Checking if session is read-write.
|
|
CONNECTION_CONSUME, ## Consuming any extra messages.
|
|
CONNECTION_GSS_STARTUP, ## Negotiating GSSAPI.
|
|
CONNECTION_CHECK_TARGET, ## Checking target server properties.
|
|
CONNECTION_CHECK_STANDBY ## Checking if server is in standby mode.
|
|
|
|
|
|
proc PQconnectdbParams(
|
|
keywords: cstringArray; values: cstringArray; expand_dbname: cint): PGconn {.libpq.}
|
|
|
|
proc PQerrorMessage(conn: PGconn): cstring {.libpq.}
|
|
proc PQfinish(conn: PGconn) {.libpq.}
|
|
proc PQstatus(conn: PGconn): ConnStatusType {.libpq.}
|
|
|
|
# proc PQsocket(conn: PGconn): cint
|
|
# proc PQconnectStartParams(
|
|
# keywords: cstringArray; values: cstringArray; expand_dbname: cint): PGconn
|
|
# TODO: async
|
|
|
|
|
|
type StringPairs = seq[tuple[key: string, val: string]]
|
|
|
|
proc splitParams(params: StringPairs): (cstringArray, cstringArray) =
|
|
var strings = newSeq[string](params.len)
|
|
for i, _ in params: strings[i] = params[i][0]
|
|
result[0] = allocCStringArray(strings)
|
|
for i, _ in params: strings[i] = params[i][1]
|
|
result[1] = allocCStringArray(strings)
|
|
|
|
proc spawnPostgreActor*(turn: var Turn; root: Cap): Actor {.discardable.} =
|
|
spawn("postgre", turn) do (turn: var Turn):
|
|
during(turn, root, ?:PostgreArguments) do (params: StringPairs, ds: Cap):
|
|
var
|
|
conn: PGconn
|
|
statusHandle: Handle
|
|
block:
|
|
var (keys, vals) = splitParams(params)
|
|
conn = PQconnectdbParams(keys, vals, 0)
|
|
deallocCStringArray(keys)
|
|
deallocCStringArray(vals)
|
|
if conn.isNil: raise newException(OutOfMemDefect, "failed to alloc PQ connection")
|
|
let
|
|
status = PQstatus(conn)
|
|
msg = $PQerrorMessage(conn)
|
|
statusHandle = publish(turn, ds,
|
|
initRecord("status", toSymbol($status), msg.toPreserves))
|
|
if status == CONNECTION_OK:
|
|
discard
|
|
do:
|
|
PQfinish(conn)
|
|
|
|
when isMainModule:
|
|
runActor("main") do (turn: var Turn; root: Cap):
|
|
connectStdio(turn, root)
|
|
spawnPostgreActor(turn, root)
|