Establish a connection to an EdgeDB server.
The connection parameters may be specified either as a connection URI in dsn, or as specific keyword arguments, or both. If both dsn and keyword arguments are specified, the latter override the corresponding values parsed from the connection URI.
Returns a new AsyncIOConnection
object.
dsn
(str
) – If this parameter does not start with edgedb://
then this is
a name of an instance.Otherwise it specifies a single string in the following format:
edgedb://user:password@host:port/database?option=value
.
The following options are recognized: host, port,
user, database, password.
host
– Database host address as one of the following:
EDGEDB_HOST
environment variable,"/run/edgedb"
and "/var/run/edgedb"
,"localhost"
.port
– Port number to connect to at the server host
(or Unix-domain socket file extension). If multiple host
addresses were specified, this parameter may specify a
sequence of port numbers of the same length as the host sequence,
or it may specify a single port number to be used for all host
addresses.If not specified, the value parsed from the dsn argument is used,
or the value of the EDGEB_PORT
environment variable, or 5656
if neither is specified.
admin
– If True
, try to connect to the special administration socket.
user
– The name of the database role used for authentication.If not specified, the value parsed from the dsn argument is used,
or the value of the EDGEDB_USER
environment variable, or the
operating system name of the user running the application.
database
– The name of the database to connect to.If not specified, the value parsed from the dsn argument is used,
or the value of the EDGEDB_DATABASE
environment variable, or the
operating system name of the user running the application.
password
– Password to be used for authentication, if the server requires
one. If not specified, the value parsed from the dsn argument
is used, or the value of the EDGEDB_PASSWORD
environment variable.
Note that the use of the environment variable is discouraged as
other users and applications may be able to read it without needing
specific privileges.
timeout
(float
) – Connection timeout in seconds.
A AsyncIOConnection
instance.
Example:
>>>
import asyncio
>>>
import edgedb
>>> ... ...
async def main():
con = await edgedb.async_connect(user='edgedeb')
print(await con.query_one('SELECT 1 + 1'))
...
>>>
asyncio.run(main())
{2}
A representation of a database session.
Connections are created by calling async_connect()
.
Run a query and return the results as a
edgedb.Set
instance.
query
(str
) – Query text.
args
– Positional query arguments.
kwargs
– Named query arguments.
An instance of edgedb.Set
containing
the query result.
Note that positional and named query arguments cannot be mixed.
Run a singleton-returning query and return its element.
query
(str
) – Query text.
args
– Positional query arguments.
kwargs
– Named query arguments.
Query result.
The query must return exactly one element. If the query returns
more than one element, an edgedb.ResultCardinalityMismatchError
is raised, if it returns an empty set, an edgedb.NoDataError
is raised.
Note, that positional and named query arguments cannot be mixed.
Run a query and return the results as JSON.
query
(str
) – Query text.
args
– Positional query arguments.
kwargs
– Named query arguments.
A JSON string containing an array of query results.
Note, that positional and named query arguments cannot be mixed.
Caution is advised when reading decimal
values using
this method. The JSON specification does not have a limit
on significant digits, so a decimal
number can be
losslessly represented in JSON. However, the default JSON
decoder in Python will read all such numbers as float
values, which may result in errors or precision loss. If
such loss is unacceptable, then consider casting the value
into str
and decoding it on the client side into a
more appropriate type, such as Decimal
.
Run a singleton-returning query and return its element in JSON.
query
(str
) – Query text.
args
– Positional query arguments.
kwargs
– Named query arguments.
Query result encoded in JSON.
The query must return exactly one element. If the query returns
more than one element, an edgedb.ResultCardinalityMismatchError
is raised, if it returns an empty set, an edgedb.NoDataError
is raised.
Note, that positional and named query arguments cannot be mixed.
Caution is advised when reading decimal
values using
this method. The JSON specification does not have a limit
on significant digits, so a decimal
number can be
losslessly represented in JSON. However, the default JSON
decoder in Python will read all such numbers as float
values, which may result in errors or precision loss. If
such loss is unacceptable, then consider casting the value
into str
and decoding it on the client side into a
more appropriate type, such as Decimal
.
Execute an EdgeQL command (or commands).
query
(str
) – Query text.
The commands must take no arguments.
Example:
>>> ... ... ... ... ... ...
await con.execute('''
CREATE TYPE MyType {
CREATE PROPERTY a -> int64
};
FOR x IN {100, 200, 300}
UNION INSERT MyType { a := x };
''')
If the results of query are desired, query()
or
query_one()
should be used instead.
Start a transaction with auto-retry semantics.
This is the preferred method of initiating and running a database
transaction in a robust fashion. The retrying_transaction()
transaction loop will attempt to re-execute the transaction loop
body if a transient error occurs, such as a network error or a
transaction serialization error.
Returns an instance of AsyncIORetry
.
See Transactions for more details.
Example:
async for tx in con.retrying_transaction():
async with tx:
value = await tx.query_one("SELECT Counter.value")
await tx.execute(
"UPDATE Counter SET { value := <int64>$value }",
value=value + 1,
)
Note that we are executing queries on the tx
object rather
than on the original connection.
Start a low-level transaction.
Unlike retrying_transaction()
, raw_transaction()
will not attempt to re-run the nested code block in case a retryable
error happens.
This is a low-level API and it is advised to use the
retrying_transaction()
method instead.
A call to raw_transaction()
returns
AsyncIOTransaction
.
Example:
async with con.raw_transaction() as tx:
value = await tx.query_one("SELECT Counter.value")
await tx.execute(
"UPDATE Counter SET { value := <int64>$value }",
value=value + 1,
)
Note that we are executing queries on the tx
object,
rather than on the original connection con
.
Deprecated. Use retrying_transaction()
or
raw_transaction()
.
Create a AsyncIOTransaction
object.
isolation
– Transaction isolation mode, can be one of:
'serializable'
, 'repeatable_read'
. If not specified,
the server-side default is used.
readonly
– Specifies whether or not this transaction is read-only. If not
specified, the server-side default is used.
deferrable
– Specifies whether or not this transaction is deferrable. If not
specified, the server-side default is used.
Close the connection gracefully.
Return True
if the connection is closed.
Create an asynchronous connection pool.
dsn
(str
) – Connection arguments specified using as a single string in
the following format:
edgedb://user:pass@host:port/database?option=value
.
**connect_kwargs
– Keyword arguments for the async_connect()
function.
connection_class
(AsyncIOConnection
) – The class to use for connections. Must be a subclass of
AsyncIOConnection
.
min_size
(int
) – Number of connections the pool will be initialized with.
max_size
(int
) – Max number of connections in the pool.
on_acquire
– A coroutine to prepare a connection right before it is returned
from Pool.acquire()
.
on_release
– A coroutine called when a connection is about to be released
to the pool.
on_connect
– A coroutine to initialize a connection when it is created.
An instance of AsyncIOPool
.
The connection pool has high-level APIs to access Connection[link] APIs directly, without manually acquiring and releasing connections from the pool:
async with edgedb.create_async_pool(user='edgedb') as pool:
await pool.query('SELECT {1, 2, 3}')
Transactions can be executed as well:
async with edgedb.create_async_pool(user='edgedb') as pool:
async for tx in pool.retrying_transaction():
async with tx:
await tx.query('SELECT {1, 2, 3}')
To hold on to a specific connection object, use the pool.acquire()
API:
async with edgedb.create_async_pool(user='edgedb') as pool:
async with pool.acquire() as con:
await con.query('SELECT {1, 2, 3}')
Or directly await
:
pool = await edgedb.create_async_pool(user='edgedb')
con = await pool.acquire()
try:
await con.query('SELECT {1, 2, 3}')
finally:
await pool.release(con)
A connection pool.
A connection pool can be used to manage a set of connections to the database. Connections are first acquired from the pool, then used, and then released back to the pool. Once a connection is released, it’s reset to close all open cursors and other resources except prepared statements.
Pools are created by calling
create_async_pool()
.
Acquire a database connection from the pool.
An instance of AsyncIOConnection
.
Can be used in an await
expression or with an async with
block.
async with pool.acquire() as con:
await con.execute(...)
Or:
con = await pool.acquire()
try:
await con.execute(...)
finally:
await pool.release(con)
Release a database connection back to the pool.
connection
(AsyncIOConnection
) – A AsyncIOConnection
object
to release.
Attempt to gracefully close all connections in the pool.
Wait until all pool connections are released, close them and
shut down the pool. If any error (including cancellation) occurs
in close()
the pool will terminate by calling
Pool.terminate()
.
It is advisable to use asyncio.wait_for()
to set
a timeout.
Terminate all connections in the pool.
Expire all currently open connections.
Cause all currently open connections to get replaced on the
next acquire()
call.
Set the new connection arguments for this pool.
dsn
(str
) – If this parameter does not start with edgedb://
then this is
a name of an instance.Otherwise it specifies a single string in the following format:
edgedb://user:pass@host:port/database?option=value
.
**connect_kwargs
– Keyword arguments for the async_connect()
function.
The new connection arguments will be used for all subsequent
new connection attempts. Existing connections will remain until
they expire. Use Pool.expire_connections()
to expedite
the connection expiry.
Acquire a connection and use it to run a query and return the results
as an edgedb.Set
instance. The temporary
connection is automatically returned back to the pool.
See AsyncIOConnection.query()
for details.
Acquire a connection and use it to run a singleton-returning query and return its element. The temporary connection is automatically returned back to the pool.
See AsyncIOConnection.query_one()
for details.
Acquire a connection and use it to run a query and return the results as JSON. The temporary connection is automatically returned back to the pool.
See AsyncIOConnection.query_json()
for details.
Acquire a connection and use it to run a singleton-returning query and return its element in JSON. The temporary connection is automatically returned back to the pool.
See AsyncIOConnection.query_one_json()
for details.
Acquire a connection and use it to execute an EdgeQL command (or commands). The temporary connection is automatically returned back to the pool.
See AsyncIOConnection.execute()
for details.
Open a retryable transaction loop.
This is the preferred method of initiating and running a database
transaction in a robust fashion. The retrying_transaction()
transaction loop will attempt to re-execute the transaction loop body
if a transient error occurs, such as a network error or a transaction
serialization error.
Returns an instance of AsyncIORetry
.
See Transactions for more details.
Example:
async for tx in pool.retrying_transaction():
async with tx:
value = await tx.query_one("SELECT Counter.value")
await tx.execute(
"UPDATE Counter SET { value := <int64>$value",
value=value,
)
Note that we are executing queries on the tx
object rather
than on the original pool.
Execute a non-retryable transaction.
Contrary to retrying_transaction()
, raw_transaction()
will not attempt to re-run the nested code block in case a retryable
error happens.
This is a low-level API and it is advised to use the
retrying_transaction()
method instead.
A call to raw_transaction()
returns
AsyncIOTransaction
.
Example:
async with pool.raw_transaction() as tx:
value = await tx.query_one("SELECT Counter.value")
await tx.execute(
"UPDATE Counter SET { value := <int64>$value",
value=value,
)
Note executing queries on tx
object rather than the original
pool.
The most robust way to execute transactional code is to use
the retrying_transaction()
loop API:
async for tx in pool.retrying_transaction():
async with tx:
await tx.execute("INSERT User { name := 'Don' }")
Note that we execute queries on the tx
object in the above
example, rather than on the original connection pool pool
object.
The retrying_transaction()
API guarantees that:
Transactions are executed atomically;
If a transaction is failed for any of the number of transient errors (i.e. a network failure or a concurrent update error), the transaction would be retried;
If any other, non-retryable exception occurs, the transaction is rolled
back, and the exception is propagated, immediately aborting the
retrying_transaction()
block.
The key implication of retrying transactions is that the entire nested code block can be re-run, including any non-querying Python code. Here is an example:
async for tx in pool.retrying_transaction():
async with tx:
user = await tx.query_one(
"SELECT User { email } FILTER .login = <str>$login",
login=login,
)
data = await httpclient.get(
'https://service.local/email_info',
params=dict(email=user.email),
)
user = await tx.query_one('''
UPDATE User FILTER .login = <str>$login
SET { email_info := <json>$data}
''',
login=login,
data=data,
)
In the above example, the execution of the HTTP request would be retried too. The core of the issue is that whenever transaction is interrupted user might have the email changed (as the result of concurrent transaction), so we have to redo all the work done.
Generally it’s recommended to not execute any long running code within the transaction unless absolutely necessary.
Transactions allocate expensive server resources and having too many concurrently running long-running transactions will negatively impact the performance of the DB server.
See also:
Represents a transaction or a savepoint block.
Instances of this type are created by calling the
AsyncIOConnection.raw_transaction()
method.
Start a transaction or create a savepoint.
Exit the transaction or savepoint block and commit changes.
Exit the transaction or savepoint block and discard changes.
Start and commit/rollback the transaction or savepoint block automatically when entering and exiting the code inside the context manager block.
Acquire a connection and use it to run a query and return the results
as an edgedb.Set
instance. The temporary
connection is automatically returned back to the pool.
See AsyncIOConnection.query()
for details.
Acquire a connection and use it to run a singleton-returning query and return its element. The temporary connection is automatically returned back to the pool.
See AsyncIOConnection.query_one()
for details.
Acquire a connection and use it to run a query and return the results as JSON. The temporary connection is automatically returned back to the pool.
See AsyncIOConnection.query_json()
for details.
Acquire a connection and use it to run a singleton-returning query and return its element in JSON. The temporary connection is automatically returned back to the pool.
See AsyncIOConnection.query_one_json()
for details.
Acquire a connection and use it to execute an EdgeQL command (or commands). The temporary connection is automatically returned back to the pool.
See AsyncIOConnection.execute()
for details.
Represents a wrapper that yields AsyncIOTransaction
object when iterating.
See AsyncIOConnection.retrying_transaction()
method for an example.
Yields AsyncIOTransaction
object every time transaction
has to be repeated.