Skip to content
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

Add execute_many, fetch_row, fetch_val to connection; impove docstrings #24

Merged
merged 6 commits into from
Mar 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 7 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,6 @@ db_pool = PSQLPool(
)

async def main() -> None:
await db_pool.startup()

res: QueryResult = await db_pool.execute(
"SELECT * FROM users",
)
Expand Down Expand Up @@ -147,10 +145,12 @@ As connection can be closed in different situations on various sides you can sel
rendered ineffective.

## Results from querying

You have some options to get results from the query.
`execute()` method, for example, returns `QueryResult` and this class can be converted into `list` of `dict`s - `list[dict[Any, Any]]` or into any Python class (`pydantic` model, as an example).

Let's see some code:

```python
from typing import Any

Expand All @@ -169,8 +169,6 @@ db_pool = PSQLPool(
)

async def main() -> None:
await db_pool.startup()

res: QueryResult = await db_pool.execute(
"SELECT * FROM users",
)
Expand Down Expand Up @@ -213,8 +211,6 @@ db_pool = PSQLPool(
)

async def main() -> None:
await db_pool.startup()

connection = await db_pool.connection()

res: QueryResult = await connection.execute(
Expand Down Expand Up @@ -252,8 +248,6 @@ from psqlpy import PSQLPool, IsolationLevel, QueryResult
db_pool = PSQLPool()

async def main() -> None:
await db_pool.startup()

connection = await db_pool.connection()
async with connection.transaction() as transaction:
res: QueryResult = await transaction.execute(
Expand All @@ -276,8 +270,6 @@ from psqlpy import PSQLPool, IsolationLevel
db_pool = PSQLPool()

async def main() -> None:
await db_pool.startup()

connection = await db_pool.connection()
transaction = connection.transaction(
isolation_level=IsolationLevel.Serializable,
Expand Down Expand Up @@ -310,8 +302,6 @@ from psqlpy import PSQLPool, IsolationLevel
db_pool = PSQLPool()

async def main() -> None:
await db_pool.startup()

connection = await db_pool.connection()
transaction = connection.transaction(
isolation_level=IsolationLevel.Serializable,
Expand Down Expand Up @@ -339,8 +329,6 @@ from psqlpy import PSQLPool, IsolationLevel
db_pool = PSQLPool()

async def main() -> None:
await db_pool.startup()

connection = await db_pool.connection()
transaction = connection.transaction(
isolation_level=IsolationLevel.Serializable,
Expand All @@ -367,8 +355,6 @@ from psqlpy import PSQLPool, IsolationLevel
db_pool = PSQLPool()

async def main() -> None:
await db_pool.startup()

connection = await db_pool.connection()
transaction = connection.transaction(
isolation_level=IsolationLevel.Serializable,
Expand All @@ -383,13 +369,15 @@ async def main() -> None:
```

### Transaction pipelining

When you have a lot of independent queries and want to execute them concurrently, you can use `pipeline`.
Pipelining can improve performance in use cases in which multiple,
independent queries need to be executed.
In a traditional workflow,
each query is sent to the server after the previous query completes.
In contrast, pipelining allows the client to send all of the queries to the server up front,
minimizing time spent by one side waiting for the other to finish sending data:

```
Sequential Pipelined
| Client | Server | | Client | Server |
Expand All @@ -404,9 +392,11 @@ minimizing time spent by one side waiting for the other to finish sending data:
| | process query 3 |
| receive rows 3 | |
```

Read more: https://docs.rs/tokio-postgres/latest/tokio_postgres/#pipelining

Let's see some code:

```python
import asyncio

Expand All @@ -415,8 +405,6 @@ from psqlpy import PSQLPool, QueryResult

async def main() -> None:
db_pool = PSQLPool()
await db_pool.startup()

transaction = await db_pool.transaction()

results: list[QueryResult] = await transaction.pipeline(
Expand Down Expand Up @@ -450,8 +438,6 @@ from psqlpy import PSQLPool, IsolationLevel
db_pool = PSQLPool()

async def main() -> None:
await db_pool.startup()

connection = await db_pool.connection()
transaction = connection.transaction(
isolation_level=IsolationLevel.Serializable,
Expand Down Expand Up @@ -484,8 +470,6 @@ from psqlpy import PSQLPool, IsolationLevel
db_pool = PSQLPool()

async def main() -> None:
await db_pool.startup()

connection = await db_pool.connection()
transaction = connection.transaction(
isolation_level=IsolationLevel.Serializable,
Expand Down Expand Up @@ -524,8 +508,6 @@ from psqlpy import PSQLPool, IsolationLevel, QueryResult
db_pool = PSQLPool()

async def main() -> None:
await db_pool.startup()

connection = await db_pool.connection()
transaction = connection.transaction(
isolation_level=IsolationLevel.Serializable,
Expand Down Expand Up @@ -553,6 +535,7 @@ async def main() -> None:
```

### Cursor as an async context manager

```python
from typing import Any

Expand All @@ -563,8 +546,6 @@ db_pool = PSQLPool()


async def main() -> None:
await db_pool.startup()

connection = await db_pool.connection()
transaction: Transaction
cursor: Cursor
Expand Down Expand Up @@ -624,8 +605,6 @@ from psqlpy.extra_types import (
db_pool = PSQLPool()

async def main() -> None:
await db_pool.startup()

res: list[dict[str, Any]] = await db_pool.execute(
"INSERT INTO users VALUES ($1, $2, $3, $4, $5)",
[
Expand Down
8 changes: 4 additions & 4 deletions docs/examples/aiohttp/start_example.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Start example
import asyncio
from typing import cast
from typing import Any, cast

from aiohttp import web
from psqlpy import PSQLPool

Expand All @@ -11,7 +12,6 @@ async def start_db_pool(app: web.Application) -> None:
dsn="postgres://postgres:postgres@localhost:5432/postgres",
max_db_pool_size=2,
)
await db_pool.startup()

app["db_pool"] = db_pool

Expand All @@ -22,7 +22,7 @@ async def stop_db_pool(app: web.Application) -> None:
await db_pool.close()


async def pg_pool_example(request: web.Request):
async def pg_pool_example(request: web.Request) -> Any:
db_pool = cast(PSQLPool, request.app["db_pool"])
connection = await db_pool.connection()
await asyncio.sleep(10)
Expand All @@ -37,7 +37,7 @@ async def pg_pool_example(request: web.Request):

application = web.Application()
application.on_startup.append(start_db_pool)
application.add_routes([web.get('/', pg_pool_example)])
application.add_routes([web.get("/", pg_pool_example)])


if __name__ == "__main__":
Expand Down
15 changes: 7 additions & 8 deletions docs/examples/fastapi/advanced_example.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# Start example
import asyncio
from contextlib import asynccontextmanager
from typing import Annotated, AsyncGenerator, cast
from fastapi import Depends, FastAPI, Request
from fastapi.responses import JSONResponse
from psqlpy import PSQLPool, Connection
import uvicorn
from typing import AsyncGenerator

import uvicorn
from fastapi import FastAPI
from fastapi.responses import JSONResponse
from psqlpy import PSQLPool

db_pool = PSQLPool(
dsn="postgres://postgres:postgres@localhost:5432/postgres",
Expand All @@ -17,7 +17,6 @@
@asynccontextmanager
async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]:
"""Startup database connection pool and close it on shutdown."""
await db_pool.startup()
app.state.db_pool = db_pool
yield
await db_pool.close()
chandr-andr marked this conversation as resolved.
Show resolved Hide resolved
Expand All @@ -34,7 +33,7 @@ async def some_long_func() -> None:


@app.get("/")
async def pg_pool_example():
async def pg_pool_example() -> JSONResponse:
await some_long_func()
db_connection = await db_pool.connection()
query_result = await db_connection.execute(
Expand All @@ -47,4 +46,4 @@ async def pg_pool_example():
uvicorn.run(
"advanced_example:app",
port=8001,
)
)
13 changes: 7 additions & 6 deletions docs/examples/fastapi/start_example.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
# Start example
from contextlib import asynccontextmanager
from typing import Annotated, AsyncGenerator, cast
from typing import AsyncGenerator, cast

import uvicorn
from fastapi import Depends, FastAPI, Request
from fastapi.responses import JSONResponse
from psqlpy import PSQLPool, Connection
import uvicorn
from psqlpy import Connection, PSQLPool
from typing_extensions import Annotated


@asynccontextmanager
Expand All @@ -14,7 +16,6 @@ async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]:
dsn="postgres://postgres:postgres@localhost:5432/postgres",
max_db_pool_size=2,
)
await db_pool.startup()
app.state.db_pool = db_pool
yield
await db_pool.close()
chandr-andr marked this conversation as resolved.
Show resolved Hide resolved
Expand All @@ -31,7 +32,7 @@ async def db_connection(request: Request) -> Connection:
@app.get("/")
async def pg_pool_example(
db_connection: Annotated[Connection, Depends(db_connection)],
):
) -> JSONResponse:
query_result = await db_connection.execute(
"SELECT * FROM users",
)
Expand All @@ -41,4 +42,4 @@ async def pg_pool_example(
if __name__ == "__main__":
uvicorn.run(
"start_example:app",
)
)
Loading
Loading