Skip to content
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
2 changes: 1 addition & 1 deletion docs/contribute.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ One of the best ways is follow [maturin offical documentation](https://www.matur
```bash
> python3 -m venv .venv
> source .venv/bin/activate
> pip install -U pip maturin
> pip install -U pip maturin pre-commit pytest pytest-anyio pydantic pgpq
```

Then you need to build `PSQLPy` project.
Expand Down
30 changes: 15 additions & 15 deletions docs/usage/types/advanced_type_usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Due to an unavailability to support all possible types in PostgreSQL, we have a
This section has `Advanced` in the name because you'll need to work with raw bytes which can be difficult for some developers.

## Pass unsupported type into PostgreSQL
If you are using some type that we don't support and want to insert it into PostgreSQL from PSQLPy, you must use `PyCustomType` class.
If you are using some type that we don't support and want to insert it into PostgreSQL from PSQLPy, you must use `CustomType` class.

Let's assume we have table `for_test` in the database and `PSQLPy` doesn't support (only for demonstration) `VARCHAR` type:
| database type | database column name |
Expand All @@ -16,24 +16,24 @@ Let's assume we have table `for_test` in the database and `PSQLPy` doesn't suppo
from typing import Final

from psqlpy import ConnectionPool
from psqlpy.extra_types import PyCustomType
from psqlpy.extra_types import CustomType


async def main() -> None:
# It uses default connection parameters
db_pool: Final = ConnectionPool()

await db_pool.execute(
"INSERT INTO for_test (nickname) VALUES ($1)",
[PyCustomType(b"SomeDataInBytes")],
)
db_pool.close()
async with db_pool.acquire() as connection:
await connection.execute(
"INSERT INTO for_test (nickname) VALUES ($1)",
[CustomType(b"SomeDataInBytes")],
)
```

Here we pass `PyCustomType` into the parameters. It accepts only bytes.
Here we pass `CustomType` into the parameters. It accepts only bytes.

::: important
You must make bytes passed into `PyCustomType` readable for `PostgreSQL`.
You must make bytes passed into `CustomType` readable for `PostgreSQL`.
If bytes will be wrong, you will get an exception.
:::

Expand All @@ -49,7 +49,7 @@ Let's assume we have table `for_test` in the database and `PSQLPy` doesn't suppo
from typing import Final, Any

from psqlpy import ConnectionPool, QueryResult
from psqlpy.extra_types import PyCustomType
from psqlpy.extra_types import CustomType


def nickname_decoder(bytes_from_psql: bytes | None) -> str:
Expand All @@ -60,17 +60,17 @@ async def main() -> None:
# It uses default connection parameters
db_pool: Final = ConnectionPool()

result: QueryResult = await db_pool.execute(
"SELECT * FROM for_test",
[PyCustomType(b"SomeDataInBytes")],
)
async with db_pool.acquire() as connection:
result: QueryResult = await connection.execute(
"SELECT * FROM for_test",
[CustomType(b"SomeDataInBytes")],
)

parsed_result: list[dict[str, Any]] = result.result(
custom_decoders={
"nickname": nickname_decoder,
},
)
db_pool.close()
```

::: important
Expand Down
13 changes: 7 additions & 6 deletions docs/usage/types/array_types.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,11 @@ from psqlpy.extra_types import TextArray

async def main() -> None:
pool = ConnectionPool()
result = await pool.execute(
querystring="SELECT * FROM users WHERE name = ANY($1)",
parameters=[
TextArray(["Alex", "Dev", "Who"]),
]
)
async with db_pool.acquire() as connection:
result = await connection.execute(
querystring="SELECT * FROM users WHERE name = ANY($1)",
parameters=[
TextArray(["Alex", "Dev", "Who"]),
]
)
```
93 changes: 45 additions & 48 deletions docs/usage/types/extra_types.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,11 @@ from psqlpy.extra_types import SmallInt, Integer, BigInt, Float32, Float64
async def main() -> None:
# It uses default connection parameters
db_pool: Final = ConnectionPool()

await db_pool.execute(
"INSERT INTO numbers (index, elf_life, elon_musk_money) VALUES ($1, $2, $3, $4, $5)",
[SmallInt(101), Integer(10500), BigInt(300000000000), Float32(123.11), Float64(222.12)],
)
db_pool.close()
async with db_pool.acquire() as connection:
await connection.execute(
"INSERT INTO numbers (index, elf_life, elon_musk_money) VALUES ($1, $2, $3, $4, $5)",
[SmallInt(101), Integer(10500), BigInt(300000000000), Float32(123.11), Float64(222.12)],
)
```

::: important
Expand Down Expand Up @@ -96,16 +95,16 @@ async def main() -> None:
# It uses default connection parameters
db_pool: Final = ConnectionPool()

await db_pool.execute(
"INSERT INTO banners (title, description) VALUES ($1, $2)",
["SomeTitle", PyText("Very long description")],
)
# Alternatively, you can do this:
await db_pool.execute(
"INSERT INTO banners (title, description) VALUES ($1, $2)",
[PyVarChar("SomeTitle"), PyText("Very long description")],
)
db_pool.close()
async with db_pool.acquire() as connection:
await connection.execute(
"INSERT INTO banners (title, description) VALUES ($1, $2)",
["SomeTitle", PyText("Very long description")],
)
# Alternatively, you can do this:
await connection.execute(
"INSERT INTO banners (title, description) VALUES ($1, $2)",
[PyVarChar("SomeTitle"), PyText("Very long description")],
)
```

## PyJSON & PyJSONB
Expand Down Expand Up @@ -140,6 +139,7 @@ from psqlpy.extra_types import PyJSON
async def main() -> None:
# It uses default connection parameters
db_pool: Final = ConnectionPool()

list_for_jsonb_field = [
{"some": "dict"},
[
Expand All @@ -154,16 +154,15 @@ async def main() -> None:
]
}

await db_pool.execute(
"INSERT INTO users (additional_user_info) VALUES ($1)",
[PyJSONB(list_for_jsonb_field)],
)
await db_pool.execute(
"INSERT INTO users (additional_user_info) VALUES ($1)",
[dict_for_jsonb_field,],
)

db_pool.close()
async with db_pool.acquire() as connection:
await connection.execute(
"INSERT INTO users (additional_user_info) VALUES ($1)",
[PyJSONB(list_for_jsonb_field)],
)
await connection.execute(
"INSERT INTO users (additional_user_info) VALUES ($1)",
[dict_for_jsonb_field,],
)
```

## PyMacAddr6 & PyMacAddr8
Expand All @@ -186,15 +185,14 @@ async def main() -> None:
# It uses default connection parameters
db_pool: Final = ConnectionPool()

await db_pool.execute(
"INSERT INTO devices (device_macaddr6, device_macaddr8) VALUES ($1, $2)",
[
PyMacAddr6("08:00:2b:01:02:03"),
PyMacAddr8("08:00:2b:01:02:03:04:05"),
],
)

db_pool.close()
async with db_pool.acquire() as connection:
await connection.execute(
"INSERT INTO devices (device_macaddr6, device_macaddr8) VALUES ($1, $2)",
[
PyMacAddr6("08:00:2b:01:02:03"),
PyMacAddr8("08:00:2b:01:02:03:04:05"),
],
)
```

## Geo Types
Expand Down Expand Up @@ -222,17 +220,16 @@ async def main() -> None:
# It uses default connection parameters
db_pool: Final = ConnectionPool()

await db_pool.execute(
"INSERT INTO geo_info VALUES ($1, $2, $3, $4, $5, $6)",
[
Point([1.5, 2]),
Box([(1.7, 2.8), (9, 9)]),
Path([(3.5, 3), (9, 9), (8, 8)]),
Line([1, -2, 3]),
LineSegment([(5.6, 3.1), (4, 5)]),
Circle([5, 1.8, 10]),
],
)

db_pool.close()
async with db_pool.acquire() as connection:
await connection.execute(
"INSERT INTO geo_info VALUES ($1, $2, $3, $4, $5, $6)",
[
Point([1.5, 2]),
Box([(1.7, 2.8), (9, 9)]),
Path([(3.5, 3), (9, 9), (8, 8)]),
Line([1, -2, 3]),
LineSegment([(5.6, 3.1), (4, 5)]),
Circle([5, 1.8, 10]),
],
)
```
41 changes: 21 additions & 20 deletions docs/usage/types/supported_types.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,11 @@ async def main() -> None:
# It uses default connection parameters
db_pool: Final = ConnectionPool()

result = await db_pool.execute(
"SELECT user_info FROM custom_table",
)
print(result.result()[0])
async with db_pool.acquire() as connection:
result = await connection.execute(
"SELECT user_info FROM custom_table",
)
print(result.result()[0])
```
It will return:
```json
Expand Down Expand Up @@ -132,22 +133,22 @@ class Weather(str, Enum):
async def main() -> None:
# It uses default connection parameters
db_pool: Final = ConnectionPool()

# Insert new data
await db_pool.execute(
querystring="INSERT INTO weather_plus VALUES($1)",
parameters=[Weather.SUN],
)

# Or you can pass string directly
await db_pool.execute(
querystring="INSERT INTO weather_plus VALUES($1)",
parameters=["sun"],
)

result = await db_pool.execute(
querystring="SELECT * FROM weather_plus",
)
async with db_pool.acquire() as connection:
# Insert new data
await connection.execute(
querystring="INSERT INTO weather_plus VALUES($1)",
parameters=[Weather.SUN],
)

# Or you can pass string directly
await connection.execute(
querystring="INSERT INTO weather_plus VALUES($1)",
parameters=["sun"],
)

result = await connection.execute(
querystring="SELECT * FROM weather_plus",
)
print(result.result()[0])
```
You will receive:
Expand Down
2 changes: 1 addition & 1 deletion src/statement/parameters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use crate::{
},
};

pub type QueryParameter = (dyn ToSql + Sync);
pub type QueryParameter = dyn ToSql + Sync;

#[pyclass]
#[derive(Default, Clone, Debug)]
Expand Down
10 changes: 3 additions & 7 deletions src/value_converter/dto/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,18 +177,14 @@ impl ToSql for PythonDTO {
<Vec<u8> as ToSql>::to_sql(pybytes, ty, out)?;
}
PythonDTO::PyBool(boolean) => types::bool_to_sql(*boolean, out),
PythonDTO::PyVarChar(string) => {
<&str as ToSql>::to_sql(&string.as_str(), ty, out)?;
}
PythonDTO::PyText(string) => {
PythonDTO::PyVarChar(string)
| PythonDTO::PyText(string)
| PythonDTO::PyString(string) => {
<&str as ToSql>::to_sql(&string.as_str(), ty, out)?;
}
PythonDTO::PyUUID(pyuuid) => {
<Uuid as ToSql>::to_sql(pyuuid, ty, out)?;
}
PythonDTO::PyString(string) => {
<&str as ToSql>::to_sql(&string.as_str(), ty, out)?;
}
PythonDTO::PyIntI16(int) => out.put_i16(*int),
PythonDTO::PyIntI32(int) => out.put_i32(*int),
PythonDTO::PyIntI64(int) | PythonDTO::PyMoney(int) => out.put_i64(*int),
Expand Down
27 changes: 7 additions & 20 deletions src/value_converter/to_python.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,14 +180,11 @@ fn postgres_bytes_to_py(
}
Ok(py.None())
}
Type::OID => Ok(
composite_field_postgres_to_py::<Option<i32>>(type_, buf, is_simple)?
.into_py_any(py)?,
),
Type::NAME => Ok(
composite_field_postgres_to_py::<Option<String>>(type_, buf, is_simple)?
.into_py_any(py)?,
),
// Convert Integer into i32, then into int
Type::OID | Type::INT4 => Ok(composite_field_postgres_to_py::<Option<i32>>(
type_, buf, is_simple,
)?
.into_py_any(py)?),
// // ---------- String Types ----------
// // Convert TEXT and VARCHAR type into String, then into str
Type::TEXT | Type::VARCHAR | Type::XML => Ok(composite_field_postgres_to_py::<
Expand All @@ -206,11 +203,6 @@ fn postgres_bytes_to_py(
composite_field_postgres_to_py::<Option<i16>>(type_, buf, is_simple)?
.into_py_any(py)?,
),
// Convert Integer into i32, then into int
Type::INT4 => Ok(
composite_field_postgres_to_py::<Option<i32>>(type_, buf, is_simple)?
.into_py_any(py)?,
),
// Convert BigInt into i64, then into int
Type::INT8 | Type::MONEY => Ok(composite_field_postgres_to_py::<Option<i64>>(
type_, buf, is_simple,
Expand Down Expand Up @@ -363,7 +355,8 @@ fn postgres_bytes_to_py(
composite_field_postgres_to_py::<Option<Array<bool>>>(type_, buf, is_simple)?,
)
.into_py_any(py)?),
Type::OID_ARRAY => Ok(postgres_array_to_py(
// Convert ARRAY of Integer into Vec<i32>, then into list[int]
Type::OID_ARRAY | Type::INT4_ARRAY => Ok(postgres_array_to_py(
py,
composite_field_postgres_to_py::<Option<Array<i32>>>(type_, buf, is_simple)?,
)
Expand All @@ -381,12 +374,6 @@ fn postgres_bytes_to_py(
composite_field_postgres_to_py::<Option<Array<i16>>>(type_, buf, is_simple)?,
)
.into_py_any(py)?),
// Convert ARRAY of Integer into Vec<i32>, then into list[int]
Type::INT4_ARRAY => Ok(postgres_array_to_py(
py,
composite_field_postgres_to_py::<Option<Array<i32>>>(type_, buf, is_simple)?,
)
.into_py_any(py)?),
// Convert ARRAY of BigInt into Vec<i64>, then into list[int]
Type::INT8_ARRAY | Type::MONEY_ARRAY => Ok(postgres_array_to_py(
py,
Expand Down
Loading