package postgres_async

  1. Overview
  2. Docs

The Expert module provides versions of all the same functions that instead return Or_pgasync_error.ts.

Note that t and Expert.t is the same type, so you can mix-and-match depending on whether you want to try and inspect the error code of a specific failure or not.

val sexp_of_t : t -> Sexplib0.Sexp.t
val connect : ?interrupt:unit Async.Deferred.t -> ?ssl_mode:Ssl_mode.t -> ?server:_ Async.Tcp.Where_to_connect.t -> ?user:string -> ?password:string -> ?gss_krb_token:string -> ?buffer_age_limit:Async_unix.Writer.buffer_age_limit -> ?buffer_byte_limit:Core.Byte_units.t -> database:string -> unit -> (t, Pgasync_error.t) Core.Result.t Async.Deferred.t

gss_krb_token will be sent in response to a server's request to initiate GSSAPI authentication. We don't support GSS/SSPI authentication that requires multiple steps; if the server sends us a "GSSContinue" message in response to gss_krb_token, login will fail. Kerberos should not require this.

ssl_mode defaults to Ssl_mode.Disable.

buffer_age_limit sets the age limit on the outgoing Writer.t. The default limit is 2m to preserve existing behavior, but you likely want `Unlimited to avoid application crashes when the database is loaded---and this may become the default at some point in the future.

buffer_byte_limit is only used during a COPY---it pauses inserting more rows and flushes the entire Writer.t if its buffer contains this many bytes or more.

close returns an error if there were any problems gracefully tearing down the connection. For sure, when it is determined, the connection is gone.

val close_finished : t -> (unit, Pgasync_error.t) Core.Result.t Async.Deferred.t
type state =
  1. | Open
  2. | Closing
  3. | Failed of {
    1. error : Pgasync_error.t;
    2. resources_released : bool;
    }
  4. | Closed_gracefully
val sexp_of_state : state -> Sexplib0.Sexp.t
val status : t -> state
val with_connection : ?interrupt:unit Async.Deferred.t -> ?ssl_mode:Ssl_mode.t -> ?server:_ Async.Tcp.Where_to_connect.t -> ?user:string -> ?password:string -> ?gss_krb_token:string -> ?buffer_age_limit:Async_unix.Writer.buffer_age_limit -> ?buffer_byte_limit:Core.Byte_units.t -> database:string -> on_handler_exception:[ `Raise ] -> (t -> 'res Async.Deferred.t) -> ('res, Pgasync_error.t) Core.Result.t Async.Deferred.t
val query : t -> ?parameters:string option array -> ?pushback:(unit -> unit Async.Deferred.t) -> ?handle_columns:(Column_metadata.t array -> unit) -> string -> handle_row:(column_names:string array -> values:string option array -> unit) -> (unit, Pgasync_error.t) Core.Result.t Async.Deferred.t

handle_columns can provide column information even if 0 rows are found. handle_columns is guaranteed to be called before the first invocation of handle_row

val query_expect_no_data : t -> ?parameters:string option array -> string -> (unit, Pgasync_error.t) Core.Result.t Async.Deferred.t
type 'a feed_data_result =
  1. | Abort of {
    1. reason : string;
    }
  2. | Wait of unit Async.Deferred.t
  3. | Data of 'a
  4. | Finished
val copy_in_raw : t -> ?parameters:string option array -> string -> feed_data:(unit -> string feed_data_result) -> (unit, Pgasync_error.t) Core.Result.t Async.Deferred.t
val copy_in_rows : ?schema_name:string -> t -> table_name:string -> column_names:string array -> feed_data:(unit -> string option array feed_data_result) -> (unit, Pgasync_error.t) Core.Result.t Async.Deferred.t

Note that table_name and column_names must be escaped before calling copy_in_rows.

val listen_to_notifications : t -> channel:string -> f:(pid:Core.Pid.t -> payload:string -> unit) -> (unit, Pgasync_error.t) Core.Result.t Async.Deferred.t

listen_to_notifications executes a query to subscribe you to notifications on channel (i.e., "LISTEN $channel") and stores f inside t, calling it when the server sends us any such notifications.

Calling it multiple times is fine: the "LISTEN" query is idempotent, and both callbacks will be stored in t.

However, be careful. The interaction between postgres notifications and transactions is very subtle. Here are but some of the things you need to bear in mind:

  • LISTEN executed during a transaction that is rolled back has no effect. As such, if you're in the middle of a transaction when you call listen_to_notifications and then roll said transaction back, f will be stored in t but you will not actually receive any notifications from the server.
  • Notifications that happen while you are in a transaction are only delivered by the server after the end of the transaction. In particular, if you're doing a big query and you're pushing-back on the server, you're also potentially delaying delivery of notifications.
  • You need to pay attention to close_finished in case the server kicks you off.
  • The postgres protocol has no heartbeats. If the server disappears in a particularly bad way it might be a while before we notice. The empty query makes a rather effective heartbeat (i.e. query_expect_no_data t ""), but this is your responsibility if you want it.
OCaml

Innovation. Community. Security.