-
Notifications
You must be signed in to change notification settings - Fork 77
feat: add support for asyncpg driver #390
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 37 commits
cda8f6c
124b732
4fa7fcc
db86be5
2a871ca
43aeb56
2489bbf
cfa17b8
7eafe68
3fe34f5
3d632a2
4348c98
bf59a2f
77dc3a7
bab8483
2445ee7
add5dfc
00ff19a
6a76007
f30a8e0
3c8f376
164037f
5f2daf0
90c66f7
b575839
f79b4eb
025da5d
4d9ce2c
85075a9
9c68d12
69bdebc
11aeea4
25b2734
cbf9d6d
9a9df43
d44c2e6
d564fdc
c12178c
4805a77
0156ceb
a1cf7ee
c357e9c
6761278
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,6 +24,7 @@ The Cloud SQL Python Connector is a package to be used alongside a database driv | |
Currently supported drivers are: | ||
- [`pymysql`](https://github.com/PyMySQL/PyMySQL) (MySQL) | ||
- [`pg8000`](https://github.com/tlocke/pg8000) (PostgreSQL) | ||
- [`asyncpg`](https://github.com/MagicStack/asyncpg) (PostgreSQL) | ||
- [`pytds`](https://github.com/denisenkom/pytds) (SQL Server) | ||
|
||
|
||
|
@@ -37,9 +38,16 @@ based on your database dialect. | |
pip install "cloud-sql-python-connector[pymysql]" | ||
``` | ||
### Postgres | ||
There are two different database drivers that are supported for the Postgres dialect: | ||
|
||
#### pg8000 | ||
``` | ||
pip install "cloud-sql-python-connector[pg8000]" | ||
``` | ||
#### asyncpg | ||
``` | ||
pip install "cloud-sql-python-connector[asyncpg]" | ||
``` | ||
### SQL Server | ||
``` | ||
pip install "cloud-sql-python-connector[pytds]" | ||
|
@@ -275,6 +283,58 @@ connector.connect( | |
) | ||
``` | ||
|
||
### Async Driver Usage | ||
The Cloud SQL Connector for Python currently supports the | ||
[asyncpg](https://magicstack.github.io/asyncpg) Postgres database driver. | ||
This driver leverages [asyncio](https://docs.python.org/3/library/asyncio.html) | ||
to improve the speed and efficiency of database connections through concurrency. | ||
|
||
The Cloud SQL Connector has an async `create_async_connector` that can be used | ||
jackwotherspoon marked this conversation as resolved.
Show resolved
Hide resolved
|
||
and is recommended for async drivers as it returns a `Connector` object | ||
that uses the current thread's running event loop automatically. | ||
|
||
The `create_async_connector` allows all the same input arguments as the | ||
[Connector](#configuring-the-connector) object. | ||
|
||
Once a `Connector` object is returned by `create_async_connector` you can call | ||
its `connect_async` method, just as you would the `connect` method: | ||
|
||
```python | ||
import asyncpg | ||
from google.cloud.sql.connector import create_async_connector | ||
|
||
async def main(): | ||
# intialize Connector object using 'create_async_connector' | ||
connector = await create_async_connector() | ||
|
||
# create connection to Cloud SQL database | ||
conn: asyncpg.Connection = await connector.connect_async( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: this connection should probably use an async with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the connector or connection itself? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The connection itself. Do we support async enters and exit with the Connector? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not currently, we don't have an There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I added the ability to create an async context manager with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, this is surprising to me that they don't support those two functions. I think it's fine to leave for now (maybe worth asking why they haven't?) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Seems like there is an open issue for it actually, if I have some spare time I will try and put up another PR to asyncpg and add the two functions. |
||
"project:region:instance", # Cloud SQL instance connection name | ||
"asyncpg", | ||
user="root", | ||
jackwotherspoon marked this conversation as resolved.
Show resolved
Hide resolved
|
||
password="shhh", | ||
db="your-db-name" | ||
# ... additional database driver args | ||
) | ||
|
||
# insert into Cloud SQL database (example) | ||
await conn.execute("INSERT INTO ratings (title, genre, rating) VALUES ('Batman', 'Action', 8.2)") | ||
|
||
# query Cloud SQL database (examples) | ||
results = await conn.fetch("SELECT * from ratings") | ||
for row in results: | ||
# ... do something with results | ||
|
||
# close asyncpg connection | ||
await conn.close | ||
|
||
# close Cloud SQL Connector | ||
await connector.close_async() | ||
``` | ||
|
||
For more details on interacting with an `asyncpg.Connection`, please visit | ||
the [official documentation](https://magicstack.github.io/asyncpg/current/api/index.html). | ||
|
||
## Support policy | ||
|
||
### Major version lifecycle | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
""" | ||
Copyright 2022 Google LLC | ||
|
||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
|
||
https://www.apache.org/licenses/LICENSE-2.0 | ||
|
||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
""" | ||
import ssl | ||
from typing import Any, TYPE_CHECKING | ||
|
||
SERVER_PROXY_PORT = 3307 | ||
|
||
if TYPE_CHECKING: | ||
import asyncpg | ||
|
||
|
||
async def connect( | ||
ip_address: str, ctx: ssl.SSLContext, **kwargs: Any | ||
) -> "asyncpg.Connection": | ||
"""Helper function to create an asyncpg DB-API connection object. | ||
|
||
:type ip_address: str | ||
:param ip_address: A string containing an IP address for the Cloud SQL | ||
instance. | ||
|
||
:type ctx: ssl.SSLContext | ||
:param ctx: An SSLContext object created from the Cloud SQL server CA | ||
cert and ephemeral cert. | ||
|
||
:type kwargs: Any | ||
:param kwargs: Keyword arguments for establishing asyncpg connection | ||
object to Cloud SQL instance. | ||
|
||
:rtype: asyncpg.Connection | ||
:returns: An asyncpg.Connection object to a Cloud SQL instance. | ||
""" | ||
try: | ||
import asyncpg | ||
except ImportError: | ||
raise ImportError( | ||
'Unable to import module "asyncpg." Please install and try again.' | ||
) | ||
user = kwargs.pop("user") | ||
db = kwargs.pop("db") | ||
passwd = kwargs.pop("password", None) | ||
|
||
return await asyncpg.connect( | ||
user=user, | ||
database=db, | ||
password=passwd, | ||
host=ip_address, | ||
port=SERVER_PROXY_PORT, | ||
ssl=ctx, | ||
direct_tls=True, | ||
**kwargs, | ||
) |
Uh oh!
There was an error while loading. Please reload this page.