///|
async fn _quick_start() -> Unit {
@async.with_task_group(group => {
let config = @client.Config::Config(
"localhost",
user="postgres",
database="app",
password="secret",
port=5432,
ssl_mode=Disable,
application_name="my-service",
)
let (client, executor) = @client.Client::create(config)
let task = group.spawn(no_wait=true, () => executor.run())
client.ready()
let current_user : String = client
.query_one("select current_user::text as current_user")
.get_name("current_user")
ignore(current_user)
client.close()
task.wait()
})
}| Need | API |
|---|---|
| Exactly one row | Client::query_one |
| Zero or one row | Client::query_opt |
| Collect every row | Client::with_stream(sql, stream => stream.collect()) |
| Incremental rows | Client::with_stream |
| Explicit parameter types | Client::with_typed_stream |
| Execute a prepared statement | Client::with_statement_stream |
| Fetch a portal window | Portal::with_stream |
| Affected row count | Client::execute |
| SQL batch without parameters | Client::batch_execute |
| Text/simple protocol frames | Client::with_simple_query |
| Bulk import/export | Client::with_copy_in, Client::with_copy_out |
///|
async fn _query_example(client : @client.Client) -> Int32 {
let input = 41
let row = client.query_one("select $1::int4 + 1 as value", params=[
input as &ToSql,
])
row.get_name("value")
}///|
async fn _first_value(client : @client.Client) -> Int32? {
client.with_stream("select generate_series(1, 100) as value", stream => {
match stream.next() {
Some(row) => Some(row.get_name("value"))
None => None
}
})
}///|
fn _accept_status(type_ : @client.Type) -> Bool {
type_.schema == Some("app") && type_.name == "status" && type_.kind is Enum(_)
}///|
async fn _prepared_example(client : @client.Client) -> Int32 {
client.with_prepared("select $1::int4 as value", statement => {
let value = 7
statement.with_stream(params=[value as &ToSql], stream => {
let result : Int32 = stream.next().unwrap().get_name("value")
result
})
})
}///|
async fn _portal_example(client : @client.Client) -> Int32 {
client.with_transaction(tx => {
tx.with_prepared("select 7::int4 as value", statement => {
statement.with_portal((portal : @client.Portal) => {
portal.with_stream(1, stream => {
let result : Int32 = stream.next().unwrap().get_name("value")
result
})
})
})
})
}///|
async fn _portal_pagination(client : @client.Client) -> Array[Int32] {
let statement = client.prepare("select generate_series(1, $1::int4) as value")
defer @async.protect_from_cancel(() => statement.close())
client.with_transaction(tx => {
tx.with_portal(statement, params=[3 as &ToSql], portal => {
let values : Array[Int32] = []
for ;; {
let summary = portal.with_stream(2, stream => {
for row in stream.collect() {
values.push(row.get_name("value"))
}
stream.finish()
})
if !summary.suspended {
break values
}
}
})
})
}///|
async fn _transaction_example(client : @client.Client) -> Unit {
client.with_transaction(tx => {
ignore(tx.execute("update accounts set active = true"))
()
})
}///|
async fn _serializable_transaction(client : @client.Client) -> Unit {
client.with_transaction(
_tx => (),
options=@client.TransactionOptions(
isolation_level=@client.IsolationLevel::Serializable,
),
)
}///|
async fn _nested_transaction_example(client : @client.Client) -> Unit {
client.with_transaction(tx => {
tx.with_savepoint("optional_work", child => {
child.with_stream("select 1", stream => ignore(stream.next()))
})
})
}///|
async fn _copy_rows(client : @client.Client) -> UInt64 {
client.with_copy_in("copy events(value) from stdin", sink => {
sink.send(b"first\nsecond\n")
sink.finish()
})
}///|
async fn _read_async_message(client : @client.Client) -> @client.AsyncMessage? {
client.next_message()
}| Fields | Meaning |
|---|---|
| severity, severity_nonlocalized | Localizable severity from S, nonlocalized severity from V |
| code, message, detail, hint | SQLSTATE, primary message, extra detail, suggested action |
| schema, table, column, datatype, constraint | Associated object names; constraint can also name an index |
| position, internal_position | One-based character indices into the submitted query and internal_query |
| internal_query, where_ | Internally generated SQL and error context (possibly multiline) |
| file, line, routine | Server source location |
///|
fn _is_email_conflict(error : Error) -> Bool {
match error {
@client.ClientError::Database(err) =>
err.code == Some("23505") && err.constraint == Some("accounts_email_key")
_ => false
}
}pub(open) trait FromSql {
fn from_sql(Type, WireFormat, BytesView) -> Self raise
fn accepts(Type) -> Bool
fn moonbit_type_name() -> String
fn from_sql_null(Type, WireFormat) -> Self raise = _
}pub suberror ClientError {
Database(DatabaseError)
Authentication(String)
NotReady
ExecutorAlreadyStarted
Closed(String)
StatementConnectionMismatch
Protocol(String)
InvalidConfig(String)
InvalidSavepointName(String)
Ssl(String)
Encode(String)
Decode(String)
WrongType(WrongTypeError)
UnsupportedRecursiveType(UInt)
ColumnNotFound(String)
RowCount(String)
UnfinishedChildTransaction
UnexpectedMessage(String)
} derive(Eq, Debug)pub enum AsyncMessage {
Notice(DatabaseError)
Notification(Notification)
ParameterStatus(String, String)
} derive(Eq, Debug)type CancelTokentype Clientfn Client::create_with_async_message_capacity(config : Config, capacity : Int) -> (Client, ClientExecutor) raiseasync fn[T] Client::with_prepared(self : Client, sql : String, f : async (ScopedStatement) -> T) -> Tasync fn[T] Client::with_prepared_typed(self : Client, sql : String, types : Array[Type], f : async (ScopedStatement) -> T) -> Tasync fn[T] Client::with_simple_query(self : Client, sql : String, f : async (SimpleQueryStream) -> T) -> Tasync fn[T] Client::with_transaction(self : Client, f : async (Transaction) -> T, options? : TransactionOptions) -> Ttype ClientExecutorpub struct Column {
name : String
table_oid : UInt
column_id : Int
type_ : Type
type_size : Int
type_modifier : Int
format : WireFormat
} derive(Eq, Debug)pub struct Config {
host : String
hostaddr : String?
port : Int
user : String
database : String
password : String?
ssl_mode : SslMode
ssl_root_cert : String?
channel_binding : ChannelBinding
application_name : String
options : String?
connect_timeout_ms : Int?
keepalives : Bool?
keepalives_idle_s : Int?
} derive(Eq)fn Config::Config(host : String, hostaddr? : String, port? : Int, user~ : String, database? : String, password? : String, ssl_mode? : SslMode, ssl_root_cert? : String, channel_binding? : ChannelBinding, application_name~ : String, options? : String, connect_timeout_ms? : Int, keepalives? : Bool, keepalives_idle_s? : Int) -> Config#internal(internal, "for internal use only")
fn Config::new_internal(host : String, hostaddr : String?, port : Int, user : String, database : String, password : String?, ssl_mode : SslMode, ssl_root_cert : String?, channel_binding : ChannelBinding, application_name : String, options : String?, connect_timeout_ms : Int?, keepalives : Bool?, keepalives_idle_s : Int?) -> Configtype CopyInSinktype CopyOutStreampub struct DatabaseError {
severity : String?
severity_nonlocalized : String?
code : String?
message : String
detail : String?
hint : String?
schema : String?
table : String?
column : String?
datatype : String?
constraint : String?
position : UInt?
internal_position : UInt?
internal_query : String?
where_ : String?
file : String?
line : UInt?
routine : String?
} derive(Eq, Debug)type Portaltype RowStreamtype ScopedStatementasync fn[T] ScopedStatement::with_portal(self : ScopedStatement, params? : Array[&ToSql], f : async (Portal) -> T) -> Tasync fn[T] ScopedStatement::with_stream(self : ScopedStatement, params? : Array[&ToSql], f : async (RowStream) -> T) -> Tpub enum SimpleQueryMessage {
RowDescription(ArrayView[String])
Row(SimpleQueryRow)
CommandComplete(String)
} derive(Eq, Debug)type SimpleQueryStreamtype Statementtype Transactionasync fn Transaction::execute_raw(self : Transaction, statement : Statement, params? : Array[&ToSql]) -> UInt64async fn Transaction::prepare_typed(self : Transaction, sql : String, types : Array[Type]) -> Statementasync fn Transaction::query_statement(self : Transaction, statement : Statement, params? : Array[&ToSql]) -> RowStreamasync fn[T] Transaction::with_portal(self : Transaction, statement : Statement, params? : Array[&ToSql], f : async (Portal) -> T) -> Tasync fn[T] Transaction::with_prepared(self : Transaction, sql : String, f : async (ScopedStatement) -> T) -> Tasync fn[T] Transaction::with_prepared_typed(self : Transaction, sql : String, types : Array[Type], f : async (ScopedStatement) -> T) -> Tasync fn[T] Transaction::with_savepoint(self : Transaction, name : String, f : async (Transaction) -> T) -> Tasync fn[T] Transaction::with_statement_stream(self : Transaction, statement : Statement, params? : Array[&ToSql], f : async (RowStream) -> T) -> Tasync fn[T] Transaction::with_stream(self : Transaction, sql : String, params? : Array[&ToSql], f : async (RowStream) -> T) -> Tpub struct TransactionOptions {
isolation_level : IsolationLevel?
read_only : Bool?
deferrable : Bool?
} derive(Eq, Debug)fn TransactionOptions::TransactionOptions(isolation_level? : IsolationLevel, read_only? : Bool, deferrable? : Bool) -> TransactionOptionsInstall
Download zipA secure, easy-to-use PostgreSQL client library for MoonBit with an included connection pool.