Basic Usage​

Connection​

The client library must be able to establish a connection to a running EdgeDB instance to execute queries. Refer to the Client Library Connection docs for details on configuring connections.

Async vs blocking API​

This libraray provides two APIs: asynchronous and blocking. Both are nearly equivalent, with the exception of connection pooling functionality, which is currently only supported in asynchronous mode.

For an async client, call create_async_client() to create an instance of AsyncIOClient. This class maintains a pool of connections under the hood and provides methods for executing queries and transactions.

For a blocking client, use connect() to create an instance of BlockingIOConnection.

Examples​

Blocking connection example:

  1. import datetime
  2. import edgedb
  3. def main():
  4. # Establish a connection to an existing database
  5. # named "test" as an "edgedb" user.
  6. conn = edgedb.connect(
  7. 'edgedb://edgedb@localhost/test')
  8. # Create a User object type
  9. conn.execute('''
  10. CREATE TYPE User {
  11. CREATE REQUIRED PROPERTY name -> str;
  12. CREATE PROPERTY dob -> cal::local_date;
  13. }
  14. ''')
  15. # Insert a new User object
  16. conn.query('''
  17. INSERT User {
  18. name := <str>$name,
  19. dob := <cal::local_date>$dob
  20. }
  21. ''', name='Bob', dob=datetime.date(1984, 3, 1))
  22. # Select User objects.
  23. user_set = conn.query(
  24. 'SELECT User {name, dob} FILTER .name = <str>$name',
  25. name='Bob')
  26. # *user_set* now contains
  27. # Set{Object{name := 'Bob',
  28. # dob := datetime.date(1984, 3, 1)}}
  29. print(user_set)
  30. # Close the connection.
  31. conn.close()
  32. if __name__ == '__main__':
  33. main()

An equivalent example using the asyncio API:

  1. import asyncio
  2. import datetime
  3. import edgedb
  4. async def main():
  5. # Establish a connection to an existing database
  6. # named "test" as an "edgedb" user.
  7. conn = await edgedb.async_connect(
  8. 'edgedb://edgedb@localhost/test')
  9. # Create a User object type
  10. await conn.execute('''
  11. CREATE TYPE User {
  12. CREATE REQUIRED PROPERTY name -> str;
  13. CREATE PROPERTY dob -> cal::local_date;
  14. }
  15. ''')
  16. # Insert a new User object
  17. await conn.query('''
  18. INSERT User {
  19. name := <str>$name,
  20. dob := <cal::local_date>$dob
  21. }
  22. ''', name='Bob', dob=datetime.date(1984, 3, 1))
  23. # Select User objects.
  24. user_set = await conn.query('''
  25. SELECT User {name, dob}
  26. FILTER .name = <str>$name
  27. ''', name='Bob')
  28. # *user_set* now contains
  29. # Set{Object{name := 'Bob',
  30. # dob := datetime.date(1984, 3, 1)}}
  31. print(user_set)
  32. # Close the connection.
  33. await conn.aclose()
  34. if __name__ == '__main__':
  35. asyncio.run(main())

Type conversion​

edgedb-python automatically converts EdgeDB types to the corresponding Python types and vice versa. See Datatypes for details.

Client connection pools​

For server-type type applications that handle frequent requests and need the database connection for a short period time while handling a request, the use of a connection pool is recommended. The edgedb-python asyncio API provides an implementation of such a pool.

To create a connection pool, use the edgedb.create_async_client() function. The resulting AsyncIOClient object can then be used to borrow connections from the pool.

Below is an example of a connection pool usage:

  1. import asyncio
  2. import edgedb
  3. from aiohttp import web
  4. async def handle(request):
  5. """Handle incoming requests."""
  6. client = request.app['client']
  7. username = int(request.match_info.get('name'))
  8. # Execute the query on any pool connection
  9. result = await client.query_single_json(
  10. '''
  11. SELECT User {first_name, email, bio}
  12. FILTER .name = <str>$username
  13. ''', username=username)
  14. return web.Response(
  15. text=result,
  16. content_type='application/json')
  17. def init_app():
  18. """Initialize the application server."""
  19. app = web.Application()
  20. # Create a database connection client
  21. app['client'] = edgedb.create_async_client(
  22. database='my_service',
  23. user='my_service')
  24. # Configure service routes
  25. app.router.add_route('GET', '/user/{name:\w+}', handle)
  26. return app
  27. loop = asyncio.get_event_loop()
  28. app = init_app()
  29. web.run_app(app)

But if you have a bunch of tightly related queries it’s better to use transactions.

Note that the client is created synchronously. Pool connections are created lazily as they are needed. If you want to explicitly connect to the database in init_app(), use the ensure_connected() method on the client.

See Client connection pool API documentation for more information.

Transactions​

The most robust way to create a transaction is the transaction() method:

Example:

  1. for tx in connection.transaction():
  2. with tx:
  3. tx.execute("INSERT User {name := 'Don'}")

or, if using the async API on connection pool:

  1. async for tx in connection.transaction():
  2. async with tx:
  3. await tx.execute("INSERT User {name := 'Don'}")

When not in an explicit transaction block, any changes to the database will be applied immediately.

See Transactions API documentation for more information.