class
CQL::Postgres::Session
- CQL::Postgres::Session
- Reference
- Object
Overview
One protocol-v3 conversation with a server over a single stream.
Every public operation takes the session's lock, so at most one request is
in flight and fibers can share a session safely (they queue). The session
counts the replies the server still owes (one ReadyForQuery per Sync or
simple query it was sent). After a ServerError, or an exception raised by
the caller's own block, nothing is owed and the session stays usable; any
failure that leaves replies unread closes it, since the stream could no
longer be matched up with requests.
#on_notice and #on_notification handlers run while the session's lock is
held, so they must not use the same session.
Defined in:
postgres/session.crpostgres/session/copying.cr
postgres/session/pipelining.cr
postgres/session/queries.cr
postgres/session/streaming.cr
Constant Summary
-
CANCEL_GRACE =
5.seconds -
Log =
::Log.for("cql.postgres") -
PING_TIMEOUT =
5.seconds -
PIPELINE_BATCH_BYTES =
32 * 1024 -
A batch is written completely before any reply is read, so it has to fit in the socket buffers: if the server's replies filled our receive buffer while we were still writing, neither side could make progress.
Constructors
-
.connect(config : Config) : Session
Connects, asking for the newest protocol the config allows.
- .new(config : Config, io : IO, outcome : Handshake::Outcome, socket : IO = io)
Instance Method Summary
-
#binary_params_sent : Int64
How many bind parameters have gone out in binary on this session (the ones
binary_paramsallowed and the server's types had a form for). -
#cancel : Nil
Asks the server, over a second connection, to cancel what this session is running.
-
#cancel_grace : Time::Span
The patience for cancelling.
-
#cancel_grace=(cancel_grace : Time::Span)
The patience for cancelling.
-
#close : Nil
Ends the session politely (Terminate) once any in-flight request is done.
- #closed? : Bool
- #config : Config
-
#copy_in(sql : String, timeout : Time::Span | Nil = nil, & : CopyIn -> ) : Int64
Streams `COPY ...
-
#copy_in_binary(sql : String, types : Array(UInt32), timeout : Time::Span | Nil = nil, & : BinaryCopy::Writer -> ) : Int64
`COPY ...
-
#copy_out(sql : String, timeout : Time::Span | Nil = nil, & : Bytes -> ) : Int64
Streams `COPY ...
-
#copy_out_binary(sql : String, types : Array(UInt32), timeout : Time::Span | Nil = nil, &on_row : Array(Types::Value) -> ) : Int64
`COPY ...
-
#encode(value) : Types::Param
A value as a bind parameter for this session, in binary if its config allows.
-
#forget_prepared_statements : Nil
Forgets every cached statement after the server dropped them (
DISCARD ALL,DEALLOCATE ALL). -
#hard_close : Nil
Drops the stream immediately.
- #in_transaction? : Bool
-
#inspect(io : IO) : Nil
Identity and state only: the cancel key, staged protocol bytes and SQL stay out of logs.
- #last_used : Time::Instant
- #on_notice : Proc(Hash(Char, String), Nil) | Nil
- #on_notice=(on_notice : Proc(Hash(Char, String), Nil) | Nil)
- #on_notification : Proc(Notification, Nil) | Nil
- #on_notification=(on_notification : Proc(Notification, Nil) | Nil)
-
#ping(timeout : Time::Span = PING_TIMEOUT) : Bool
One cheap round trip (an empty query).
-
#pipeline(statements : Array(Tuple(String, Array(Types::Param))), timeout : Time::Span | Nil = nil) : Array(Result | ServerError)
Sends several statements before reading any answer, so they cost one network round trip (two for statements not prepared yet).
- #process_id : Int32
- #protocol_version : ProtocolVersion
-
#query(sql : String, params : Array(Types::Param) = [] of Types::Param, cache : Bool = true, timeout : Time::Span | Nil = nil) : Result
Runs one statement with bound parameters through the extended protocol, preparing it once per connection when cache is on.
-
#requests : Int64
Requests run on this session so far (a pipeline counts once).
- #secret_key : Bytes
- #server_parameters : Hash(String, String)
-
#simple_query(sql : String, timeout : Time::Span | Nil = nil) : Array(Result)
Runs text with the simple protocol, which allows several statements.
-
#stream(sql : String, params : Array(Types::Param) = [] of Types::Param, fetch_size : Int32 = 1000, cache : Bool = true, timeout : Time::Span | Nil = nil, & : RowStream -> T) : T forall T
Runs one statement and yields its rows
fetch_sizeat a time (Execute with a row limit; the portal stays open between fetches). - #transaction_status : Char
Constructor Detail
Connects, asking for the newest protocol the config allows. A server that rejects that version outright (before PostgreSQL 9.3.21, or some poolers) gets one more try with 3.0 when the config allows it.
Instance Method Detail
How many bind parameters have gone out in binary on this session (the
ones binary_params allowed and the server's types had a form for).
Asks the server, over a second connection, to cancel what this session is running. Safe to call from any fiber.
The patience for cancelling. A timed-out request has this long, from the moment its timeout fires, for the cancel to take effect before its socket is closed under it. A cancel's own connect and wait for the postmaster's hang-up are each capped at it, and a request that was cancelled waits up to twice this for the cancel to finish before the session is handed on (and drops the session if it still has not).
The patience for cancelling. A timed-out request has this long, from the moment its timeout fires, for the cancel to take effect before its socket is closed under it. A cancel's own connect and wait for the postmaster's hang-up are each capped at it, and a request that was cancelled waits up to twice this for the cancel to finish before the session is handed on (and drops the session if it still has not).
Ends the session politely (Terminate) once any in-flight request is done.
The Terminate write can still wait on a dead path with a full send buffer
(the write timeout is lifted after startup); use #hard_close to cut that short.
Streams COPY ... FROM STDIN; returns the number of rows copied. If the
block raises, the COPY is aborted and the exception re-raised.
COPY ... FROM STDIN (FORMAT binary) with the signature and trailer
handled for you: types are the OIDs of the copied columns and the block
writes rows. If the block raises, the COPY is aborted like #copy_in. A
statement the server runs as text raises ArgumentError before any data moves.
engine = CQL::Postgres::AsyncEngine.connect(ENV["DATABASE_URL"])
types = [CQL::Postgres::Types::OID::INT8, CQL::Postgres::Types::OID::TEXT]
engine.with_connection do |connection|
connection.session.copy_in_binary("COPY t (id, name) FROM STDIN (FORMAT binary)", types) do |rows|
rows.row(1_i64, "a")
end
end
Streams COPY ... TO STDOUT chunks to the block; returns rows copied. If
the block raises, the remaining chunks are read and dropped before the
exception is re-raised.
COPY ... TO STDOUT (FORMAT binary): yields each row decoded by the
column types (OIDs; a type without a decoder arrives as raw bytes).
Stopping early, timeouts and cancel behave as in #copy_out; a statement the
server runs as text raises ArgumentError once its output has been read.
A value as a bind parameter for this session, in binary if its config allows.
Forgets every cached statement after the server dropped them
(DISCARD ALL, DEALLOCATE ALL).
Identity and state only: the cancel key, staged protocol bytes and SQL stay out of logs.
One cheap round trip (an empty query). If the server does not answer within timeout the socket is closed (a silently dropped path would otherwise block this forever) and the answer is false.
Sends several statements before reading any answer, so they cost one
network round trip (two for statements not prepared yet). Large batches
go out in chunks that fit the socket buffers. Each statement has its own
sync point: one failing leaves the others unaffected and shows up as a
ServerError in its slot. A timeout bounds the whole pipeline: when it
expires the running statement is canceled, the rest are abandoned, the
session is dropped and QueryTimeout is raised. A server FATAL raises the
error and drops the session; results already read are lost.
Runs one statement with bound parameters through the extended protocol, preparing it once per connection when cache is on.
Runs text with the simple protocol, which allows several statements. Every column comes back as text.
Runs one statement and yields its rows fetch_size at a time (Execute
with a row limit; the portal stays open between fetches). The session is
locked for the whole block, so use another connection inside it. When the
block ends, however early, the portal is closed and the session left in
sync, ready for the pool; the stream cannot be read afterwards. timeout
bounds the whole stream, consumer time included: once it passes, the next
fetch raises QueryTimeout and the session is dropped unless the server
confirmed a cancel. Session#cancel ends a stream that still has rows to
fetch: it cancels the fetch in progress, or, if the portal is suspended and
the server has nothing to cancel, makes the next fetch raise QueryCanceled
(rows already buffered, up to the fetch size, are still delivered first).
A cancel still in flight when the request ends is waited for (every request
does this, not only streams), so it cannot hit the session's next statement;
a cancel that lands on the stream's own cleanup is ignored. A cancel begun
while no request holds the session is not covered. COPY cannot be streamed.