Skip to content

Commit 05a6491

Browse files
authored
Merge pull request #140 from psqlpy-python/support_dbapi
Added more documentation
2 parents 4f04cff + 5bcf10f commit 05a6491

File tree

12 files changed

+160
-89
lines changed

12 files changed

+160
-89
lines changed

Cargo.toml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,14 @@ crate-type = ["cdylib"]
1010

1111
[dependencies]
1212
deadpool-postgres = { git = "https://github.com/chandr-andr/deadpool.git", branch = "psqlpy" }
13-
pyo3 = { version = "0.23.4", features = ["chrono", "experimental-async", "rust_decimal", "py-clone", "macros", "multiple-pymethods"] }
13+
pyo3 = { version = "0.23.4", features = [
14+
"chrono",
15+
"experimental-async",
16+
"rust_decimal",
17+
"py-clone",
18+
"macros",
19+
"multiple-pymethods",
20+
] }
1421
pyo3-async-runtimes = { git = "https://github.com/chandr-andr/pyo3-async-runtimes.git", branch = "psqlpy", features = [
1522
"tokio-runtime",
1623
] }

docs/.vuepress/sidebar.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,15 @@ export default sidebar({
4646
"advanced_type_usage",
4747
]
4848
},
49+
{
50+
text: "Row Factories Usage",
51+
prefix: "row_factories/",
52+
collapsible: true,
53+
children: [
54+
"row_factories",
55+
"predefined_row_factories",
56+
]
57+
},
4958
{
5059
text: "Frameworks Usage",
5160
prefix: "frameworks/",
@@ -58,15 +67,6 @@ export default sidebar({
5867
"robyn",
5968
]
6069
},
61-
{
62-
text: "Row Factories Usage",
63-
prefix: "row_factories/",
64-
collapsible: true,
65-
children: [
66-
"row_factories",
67-
"predefined_row_factories",
68-
]
69-
},
7070
],
7171
},
7272
{

docs/README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,9 @@ highlights:
2828
details: PSQLPy is under active development.
2929
---
3030
## What is PSQLPy
31-
`PSQLPy` is a new Python driver for `PostgreSQL` fully written in Rust. It was inspired by `Psycopg3` and `AsyncPG`.
31+
`PSQLPy` is a Python driver for `PostgreSQL` fully written in Rust. It was inspired by `Psycopg3` and `AsyncPG`.
3232
This project has two main goals:
33-
Make a interaction with the database as fast as possible and now `PSQLPy` shows itself to be times faster than the above drivers.
34-
Don't make useless abstractions and make it like a mirror to `PostgreSQL`.
33+
We found that communication with the database can be faster and safer, so we tried to implement a new PostgreSQL driver in Rust for Python.
3534

3635
It has all necessary components to create high-load and fault tolerance applications.
3736

@@ -59,4 +58,5 @@ pip install git+https://github.com/psqlpy-python/psqlpy
5958

6059
## Join community!
6160
You can get support from the creators and users of `PSQLPy` in some social media:
62-
- [Telegram](https://t.me/+f3Y8mYKgXxhmYThi)
61+
- [Telegram](https://t.me/+f3Y8mYKgXxhmYThi)
62+
- [Discord](https://discord.gg/ugNhzmhZ)

docs/components/connection.md

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,10 @@ async def main() -> None:
2424
```python
2525
from psqlpy import connect
2626

27-
db_connection: Final = connect(
28-
dsn="postgres://postgres:postgres@localhost:5432/postgres",
29-
)
30-
3127
async def main() -> None:
28+
db_connection: Final = await connect(
29+
dsn="postgres://postgres:postgres@localhost:5432/postgres",
30+
)
3231
await db_connection.execute(...)
3332
```
3433

docs/components/cursor.md

Lines changed: 110 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,44 +3,93 @@ title: Cursor
33
---
44

55
`Cursor` objects represents server-side `Cursor` in the `PostgreSQL`. [PostgreSQL docs](https://www.postgresql.org/docs/current/plpgsql-cursors.html).
6+
::: important
7+
Cursor always lives inside a transaction. If you don't begin transaction explicitly, it will be opened anyway.
8+
:::
69

710
## Cursor Parameters
811

912
- `querystring`: specify query for cursor.
1013
- `parameters`: parameters for the querystring. Default `None`
11-
- `fetch_number`: default fetch number. It is used in `fetch()` method and in async iterator. Default 10
12-
- `scroll`: is cursor scrollable or not. Default as in `PostgreSQL`.
14+
- `fetch_number`: default fetch number. It is used in `fetch()` method and in async iterator.
1315

14-
## Cursor as async iterator
16+
## Usage
1517

16-
The most common situation is using `Cursor` as async iterator.
18+
Cursor can be used in different ways.
1719

20+
::: tabs
21+
@tab Pre-Initialization
1822
```python
1923
from psqlpy import ConnectionPool, QueryResult
2024

25+
async def main() -> None:
26+
db_pool = ConnectionPool()
27+
connection = await db_pool.connection()
28+
29+
cursor = connection.cursor(
30+
querystring="SELECT * FROM users WHERE id > $1",
31+
parameters=[100],
32+
fetch_number=10,
33+
)
34+
await cursor.start()
35+
```
36+
37+
@tab Post-Initialization
38+
```python
39+
from psqlpy import ConnectionPool, QueryResult
2140

2241
async def main() -> None:
2342
db_pool = ConnectionPool()
43+
connection = await db_pool.connection()
44+
45+
cursor = connection.cursor()
46+
await cursor.execute(
47+
querystring="SELECT * FROM users WHERE id > $1",
48+
parameters=[100],
49+
)
50+
result: QueryResult = await cursor.fetchone()
51+
```
2452

53+
@tab Async Context Manager
54+
```python
55+
from psqlpy import ConnectionPool, QueryResult
2556

57+
async def main() -> None:
58+
db_pool = ConnectionPool()
2659
connection = await db_pool.connection()
27-
transaction = await connection.transaction()
28-
29-
# Here we fetch 5 results in each iteration.
30-
async with cursor in transaction.cursor(
31-
querystring="SELECT * FROM users WHERE username = $1",
32-
parameters=["Some_Username"],
33-
fetch_number=5,
34-
):
35-
async for fetched_result in cursor:
36-
dict_result: List[Dict[Any, Any]] = fetched_result.result()
37-
... # do something with this result.
60+
61+
async with connection.cursor(
62+
querystring="SELECT * FROM users WHERE id > $1",
63+
parameters=[100],
64+
array_size=10,
65+
) as cursor:
66+
result: QueryResult = await cursor.fetchone()
3867
```
3968

40-
## Cursor methods
69+
@tab Async Iterator
70+
```python
71+
from psqlpy import ConnectionPool, QueryResult
4172

42-
There are a lot of methods to work with cursor.
73+
async def main() -> None:
74+
db_pool = ConnectionPool()
75+
connection = await db_pool.connection()
76+
77+
cursor = connection.cursor(
78+
querystring="SELECT * FROM users WHERE id > $1",
79+
parameters=[100],
80+
fetch_number=10,
81+
)
82+
await cursor.start()
4383

84+
async for result in cursor:
85+
print(result)
86+
```
87+
:::
88+
89+
## Cursor attributes
90+
- `array_size`: get and set attribute. Used in async iterator and `fetch_many` method.
91+
92+
## Cursor methods
4493
### Start
4594
Declare (create) cursor.
4695

@@ -58,14 +107,53 @@ async def main() -> None:
58107
await cursor.close()
59108
```
60109

61-
### Fetch
110+
### Execute
62111

63-
You can fetch next `N` records from the cursor.
64-
It's possible to specify `N` fetch record with parameter `fetch_number`, otherwise will be used `fetch_number` from the `Cursor` initialization.
112+
Initialize cursor and make it ready for fetching.
113+
114+
::: important
115+
If you initialized cursor with `start` method or via context manager, you don't have to use this method.
116+
:::
117+
118+
#### Parameters:
119+
- `querystring`: specify query for cursor.
120+
- `parameters`: parameters for the querystring. Default `None`
65121

66122
```python
67123
async def main() -> None:
68-
result: QueryResult = await cursor.fetch(
69-
fetch_number=100,
124+
await cursor.execute(
125+
querystring="SELECT * FROM users WHERE id > $1",
126+
parameters=[100],
70127
)
128+
result: QueryResult = await cursor.fetchone()
129+
```
130+
131+
### Fetchone
132+
133+
Fetch one result from the cursor.
134+
135+
```python
136+
async def main() -> None:
137+
result: QueryResult = await cursor.fetchone()
138+
```
139+
140+
### Fetchmany
141+
142+
Fetch N results from the cursor. Default is `array_size`.
143+
144+
#### Parameters:
145+
- `size`: number of records to fetch.
146+
147+
```python
148+
async def main() -> None:
149+
result: QueryResult = await cursor.fetchmany(size=10)
150+
```
151+
152+
### Fetchall
153+
154+
Fetch all results from the cursor.
155+
156+
```python
157+
async def main() -> None:
158+
result: QueryResult = await cursor.fetchall()
71159
```

docs/components/transaction.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -407,8 +407,6 @@ async def main() -> None:
407407
- `querystring`: Statement string.
408408
- `parameters`: List of list of parameters for the statement string.
409409
- `fetch_number`: rewrite default fetch_number. Default is 10.
410-
- `scroll`: make cursor scrollable or not. Default is like in `PostgreSQL`.
411-
- `prepared`: prepare querystring or not.
412410

413411
From `Transaction` you can create new `Cursor` object which represents cursor in the `PostgreSQL`. [PostgreSQL Docs](https://www.postgresql.org/docs/current/plpgsql-cursors.html)
414412

docs/introduction/introduction.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,14 @@ title: What is PSQLPy?
55
`PSQLPy` is a new Python driver for PostgreSQL fully written in Rust. It was inspired by `Psycopg3` and `AsyncPG`.
66

77
With `PSQLPy` you can:
8-
- Make an interaction with the PostgeSQL in your application much faster (2-3 times).
8+
- Make an interaction with the PostgeSQL in your application faster.
99
- Be sure that there won't be any unexpected errors.
10-
- Don't usually go to the documentation to search every question - we have awesome docstrings for every component.
10+
- Don't usually go to the documentation to search every question - we have docstrings for every component.
1111
- Use `MyPy` (or any other Python type checker) with confidence that exactly the types specified in the typing will be returned.
1212
- Concentrate on writing your code, not understanding new abstractions in this library, we only have classes which represents PostgreSQL object (transaction, cursor, etc).
1313

1414
::: info
15-
It is extremely important to understand that the library will provide a noticeable acceleration in working with the database only if your queries are optimized.
16-
Otherwise, there will be acceleration, but not so significant
15+
The library will provide a noticeable acceleration in working with the database only if your queries are optimized.
1716
:::
1817

1918
## Important notes
@@ -22,4 +21,5 @@ But in some situations this behavior can break you application. As an example, i
2221

2322
## Join community!
2423
You can get support from the creators of `PSQLPy` in some social media:
25-
- [Telegram](https://t.me/+f3Y8mYKgXxhmYThi)
24+
- [Telegram](https://t.me/+f3Y8mYKgXxhmYThi)
25+
- [Discord](https://discord.gg/ugNhzmhZ)

python/tests/test_cursor.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,22 @@ async def test_cursor_as_async_context_manager(
6565
assert len(results.result()) == number_database_records
6666

6767

68+
async def test_cursor_as_async_iterator(
69+
psql_pool: ConnectionPool,
70+
table_name: str,
71+
number_database_records: int,
72+
) -> None:
73+
connection = await psql_pool.connection()
74+
all_results = []
75+
async with connection.cursor(
76+
querystring=f"SELECT * FROM {table_name}",
77+
) as cursor:
78+
async for results in cursor:
79+
all_results.extend(results.result())
80+
81+
assert len(all_results) == number_database_records
82+
83+
6884
async def test_cursor_send_underlying_connection_to_pool(
6985
psql_pool: ConnectionPool,
7086
table_name: str,

src/connection/traits.rs

Lines changed: 0 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -101,39 +101,3 @@ pub trait CloseTransaction: StartTransaction {
101101

102102
fn rollback(&mut self) -> impl std::future::Future<Output = PSQLPyResult<()>>;
103103
}
104-
105-
// pub trait Cursor {
106-
// fn build_cursor_start_qs(
107-
// &self,
108-
// cursor_name: &str,
109-
// scroll: &Option<bool>,
110-
// querystring: &str,
111-
// ) -> String {
112-
// let mut cursor_init_query = format!("DECLARE {cursor_name}");
113-
// if let Some(scroll) = scroll {
114-
// if *scroll {
115-
// cursor_init_query.push_str(" SCROLL");
116-
// } else {
117-
// cursor_init_query.push_str(" NO SCROLL");
118-
// }
119-
// }
120-
121-
// cursor_init_query.push_str(format!(" CURSOR FOR {querystring}").as_str());
122-
123-
// cursor_init_query
124-
// }
125-
126-
// fn start_cursor(
127-
// &mut self,
128-
// cursor_name: &str,
129-
// scroll: &Option<bool>,
130-
// querystring: String,
131-
// prepared: &Option<bool>,
132-
// parameters: Option<pyo3::Py<PyAny>>,
133-
// ) -> impl std::future::Future<Output = PSQLPyResult<()>>;
134-
135-
// fn close_cursor(
136-
// &mut self,
137-
// cursor_name: &str,
138-
// ) -> impl std::future::Future<Output = PSQLPyResult<()>>;
139-
// }

src/driver/common.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -132,18 +132,18 @@ macro_rules! impl_cursor_method {
132132
($name:ident) => {
133133
#[pymethods]
134134
impl $name {
135-
#[pyo3(signature = (querystring=None, parameters=None, fetch_number=None))]
135+
#[pyo3(signature = (querystring=None, parameters=None, array_size=None))]
136136
pub fn cursor(
137137
&self,
138138
querystring: Option<String>,
139139
parameters: Option<Py<PyAny>>,
140-
fetch_number: Option<i32>,
140+
array_size: Option<i32>,
141141
) -> PSQLPyResult<Cursor> {
142142
Ok(Cursor::new(
143143
self.conn.clone(),
144144
querystring,
145145
parameters,
146-
fetch_number,
146+
array_size,
147147
self.pg_config.clone(),
148148
None,
149149
))

0 commit comments

Comments
 (0)