pub struct Client<S: AsyncRead + AsyncWrite + Unpin + Send> { /* private fields */ }Expand description
Client is the main entry point to the SQL Server, providing query
execution capabilities.
A Client is created using the Config, defining the needed
connection options and capabilities.
§Example
use tokio_util::compat::TokioAsyncWriteCompatExt;
let mut config = Config::new();
config.host("0.0.0.0");
config.port(1433);
config.authentication(AuthMethod::sql_server("SA", "<Mys3cureP4ssW0rD>"));
let tcp = tokio::net::TcpStream::connect(config.get_addr()).await?;
tcp.set_nodelay(true)?;
// Client is ready to use.
let client = tiberius::Client::connect(config, tcp.compat_write()).await?;§Cancellation safety
A single Client drives one connection and one request at a time. If a
query/execute/simple_query future — or the result stream it returns —
is dropped before the request has been sent in full and the response fully
consumed (for example under a tokio::time::timeout or a select! branch
that loses the race), the connection may be left mid-message and out of sync
with the server. A cancelled write is detected and any further use of that
connection fails cleanly; a result stream dropped mid-response cannot be
recovered. In both cases the safe course is to drop the Client and open a
new connection (a connection pool should discard the connection on error)
rather than reuse it.
Implementations§
Source§impl<S: AsyncRead + AsyncWrite + Unpin + Send> Client<S>
impl<S: AsyncRead + AsyncWrite + Unpin + Send> Client<S>
Sourcepub async fn connect(config: Config, tcp_stream: S) -> Result<Client<S>>
pub async fn connect(config: Config, tcp_stream: S) -> Result<Client<S>>
Uses an instance of Config to specify the connection
options required to connect to the database using an established
tcp connection
Note: tcp_stream is a connected stream, so some parts of the Config
(such as multi-subnet failover, which selects between resolved
addresses) must be handled while establishing that stream, outside of
this constructor.
Sourcepub async fn execute<'a>(
&mut self,
query: impl Into<Cow<'a, str>>,
params: &[&dyn ToSql],
) -> Result<ExecuteResult>
pub async fn execute<'a>( &mut self, query: impl Into<Cow<'a, str>>, params: &[&dyn ToSql], ) -> Result<ExecuteResult>
Executes SQL statements in the SQL Server, returning the number rows
affected. Useful for INSERT, UPDATE and DELETE statements. The
query can define the parameter placement by annotating them with
@PN, where N is the index of the parameter, starting from 1. If
executing multiple queries at a time, delimit them with ; and refer to
ExecuteResult how to get results for the separate queries.
For mapping of Rust types when writing, see the documentation for
ToSql. For reading data from the database, see the documentation for
FromSql.
This API is not quite suitable for dynamic query parameters. In these
cases using a Query object might be easier.
§Example
let results = client
.execute(
"INSERT INTO ##Test (id) VALUES (@P1), (@P2), (@P3)",
&[&1i32, &2i32, &3i32],
)
.await?;Sourcepub async fn query<'a, 'b>(
&'a mut self,
query: impl Into<Cow<'b, str>>,
params: &'b [&'b dyn ToSql],
) -> Result<QueryStream<'a>>where
'a: 'b,
pub async fn query<'a, 'b>(
&'a mut self,
query: impl Into<Cow<'b, str>>,
params: &'b [&'b dyn ToSql],
) -> Result<QueryStream<'a>>where
'a: 'b,
Executes SQL statements in the SQL Server, returning resulting rows.
Useful for SELECT statements. The query can define the parameter
placement by annotating them with @PN, where N is the index of the
parameter, starting from 1. If executing multiple queries at a time,
delimit them with ; and refer to QueryStream on proper stream
handling.
For mapping of Rust types when writing, see the documentation for
ToSql. For reading data from the database, see the documentation for
FromSql.
This API can be cumbersome for dynamic query parameters. In these cases,
if fighting too much with the compiler, using a Query object might be
easier.
§Example
let stream = client
.query(
"SELECT @P1, @P2, @P3",
&[&1i32, &2i32, &3i32],
)
.await?;Sourcepub async fn simple_query<'a, 'b>(
&'a mut self,
query: impl Into<Cow<'b, str>>,
) -> Result<QueryStream<'a>>where
'a: 'b,
pub async fn simple_query<'a, 'b>(
&'a mut self,
query: impl Into<Cow<'b, str>>,
) -> Result<QueryStream<'a>>where
'a: 'b,
Execute multiple queries, delimited with ; and return multiple result
sets; one for each query.
§Example
let row = client.simple_query("SELECT 1 AS col").await?.into_row().await?.unwrap();
assert_eq!(Some(1i32), row.get("col"));§Warning
Do not use this with any user specified input. Please resort to prepared
statements using the query method.
Sourcepub async fn bulk_insert<'a>(
&'a mut self,
table: &'a str,
) -> Result<BulkLoadRequest<'a, S>>
pub async fn bulk_insert<'a>( &'a mut self, table: &'a str, ) -> Result<BulkLoadRequest<'a, S>>
Execute a BULK INSERT statement, efficiently storing a large number of
rows to a specified table. Note: make sure the input row follows the same
schema as the table, otherwise calling send() will return an error.
This is equivalent to calling bulk_insert("table_name", &["*"]) to merge
all of a tables columns.
§Example
let create_table = r#"
CREATE TABLE ##bulk_test (
id INT IDENTITY PRIMARY KEY,
val INT NOT NULL
)
"#;
client.simple_query(create_table).await?;
// Start the bulk insert with the client.
let mut req = client.bulk_insert("##bulk_test").await?;
for i in [0i32, 1i32, 2i32] {
let row = (i).into_row();
// The request will handle flushing to the wire in an optimal way,
// balancing between memory usage and IO performance.
req.send(row).await?;
}
// The request must be finalized.
let res = req.finalize().await?;
assert_eq!(3, res.total());Sourcepub async fn bulk_insert_columns<'a>(
&'a mut self,
table: &'a str,
columns: &'a [&'a str],
) -> Result<BulkLoadRequest<'a, S>>
pub async fn bulk_insert_columns<'a>( &'a mut self, table: &'a str, columns: &'a [&'a str], ) -> Result<BulkLoadRequest<'a, S>>
Execute a BULK INSERT statement, efficiently storing a large number of
rows to a specified table. Note: make sure the input row follows the same
schema as the column list, otherwise calling send() will return an error.
§Example
let create_table = r#"
CREATE TABLE ##bulk_test_columns (
id INT IDENTITY PRIMARY KEY,
foo INT NOT NULL,
bar FLOAT NOT NULL
)
"#;
client.simple_query(create_table).await?;
// Start the bulk insert with the client.
let mut req = client.bulk_insert_columns("##bulk_test_columns", &["foo", "bar"]).await?;
for (i, j) in [(0i32, 0f64), (1i32, 1f64), (2i32, 2f64)] {
let row = (i, j).into_row();
// The request will handle flushing to the wire in an optimal way,
// balancing between memory usage and IO performance.
req.send(row).await?;
}
// The request must be finalized.
let res = req.finalize().await?;
assert_eq!(3, res.total());Sourcepub async fn column_metadata(
&mut self,
table: &str,
columns: &[&str],
) -> Result<Vec<MetaDataColumn<'static>>>
pub async fn column_metadata( &mut self, table: &str, columns: &[&str], ) -> Result<Vec<MetaDataColumn<'static>>>
Retrieve the column metadata for a set of columns of a table, including the column names, types (with their size, precision and scale) and flags such as nullability and whether a column is an identity column.
Pass &["*"] as columns to return the metadata for every column of the
table.
let meta = client.column_metadata("some_table", &["*"]).await?;
assert!(meta[0].base().is_identity());Sourcepub async fn cancel_query(&mut self) -> Result<()>
pub async fn cancel_query(&mut self) -> Result<()>
Sends a TDS Attention signal to the server (packet type 0x06,
MS-TDS section 2.2.1.6) to cancel the request that is currently in
flight on this connection, and drains the acknowledging token stream so
the connection can be reused for further queries.
The server responds to the Attention signal by aborting the running
batch or RPC and returning a DONE token with the DONE_ATTN status
bit set. This method waits for that acknowledgement before returning,
discarding any remaining rows or tokens from the cancelled request.
§Query cancellation and futures
Dropping a query, execute or simple_query future (for
example when a tokio::time::timeout elapses or a select! branch is
cancelled) stops the client from polling the stream, but it does not
tell the server to stop working on the request. To actually cancel the
in-flight work on the server, keep the Client and call
cancel_query on it. Because cancel_query borrows the client
mutably, it can only be issued once the borrowing result stream has
been dropped — typically from a separate task holding the client, or
after a cancelled/timed-out future has released its borrow.
Sourcepub async fn begin_transaction(&mut self) -> Result<()>
pub async fn begin_transaction(&mut self) -> Result<()>
Begins a new transaction using a Transaction Manager request
(TM_BEGIN_XACT, MS-TDS 2.2.6.8) instead of a BEGIN TRAN T-SQL
batch.
On success the server replies with a BeginTransaction environment
change token whose descriptor is stored in the connection context and
automatically attached to subsequent requests, scoping them to the
transaction. Commit the work with commit_transaction or discard it
with rollback_transaction.
The transaction uses the server’s default isolation level. Use
begin_transaction_with_isolation to request a specific one.
Sourcepub async fn begin_transaction_with_isolation(
&mut self,
isolation_level: IsolationLevel,
) -> Result<()>
pub async fn begin_transaction_with_isolation( &mut self, isolation_level: IsolationLevel, ) -> Result<()>
Begins a new transaction with an explicit isolation level using a
Transaction Manager request (TM_BEGIN_XACT, MS-TDS 2.2.6.8).
See begin_transaction for details on transaction scoping.
Sourcepub async fn commit_transaction(&mut self) -> Result<()>
pub async fn commit_transaction(&mut self) -> Result<()>
Commits the active transaction using a Transaction Manager request
(TM_COMMIT_XACT, MS-TDS 2.2.6.8).
After a successful commit the connection is no longer scoped to a transaction.
Sourcepub async fn rollback_transaction(&mut self) -> Result<()>
pub async fn rollback_transaction(&mut self) -> Result<()>
Rolls back the active transaction using a Transaction Manager request
(TM_ROLLBACK_XACT, MS-TDS 2.2.6.8).
After a successful rollback the connection is no longer scoped to a transaction.
Sourcepub async fn save_transaction<'a>(
&mut self,
name: impl Into<Cow<'a, str>>,
) -> Result<()>
pub async fn save_transaction<'a>( &mut self, name: impl Into<Cow<'a, str>>, ) -> Result<()>
Creates a named savepoint in the active transaction using a Transaction
Manager request (TM_SAVE_XACT, MS-TDS 2.2.6.8).
The savepoint can later be targeted by a T-SQL ROLLBACK TRANSACTION <name> to undo work performed after it while keeping the surrounding
transaction open.