Skip to content

Commit

Permalink
Merge pull request #92 from psqlpy-python/feature/add_explicit_array_…
Browse files Browse the repository at this point in the history
…types

Added explicit array types
  • Loading branch information
chandr-andr authored Sep 29, 2024
2 parents e7c0b58 + f1cbe23 commit 901c644
Show file tree
Hide file tree
Showing 11 changed files with 1,687 additions and 53 deletions.
6 changes: 6 additions & 0 deletions docs/.vuepress/sidebar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export default sidebar({
collapsible: true,
children: [
"supported_types",
"array_types",
"extra_types",
"advanced_type_usage",
]
Expand Down Expand Up @@ -75,5 +76,10 @@ export default sidebar({
prefix: "/benchmarks",
link: "/benchmarks.md"
},
{
text: "FAQ",
prefix: "/faq",
link: "/faq.md"
},
],
});
4 changes: 3 additions & 1 deletion docs/components/connection.md
Original file line number Diff line number Diff line change
Expand Up @@ -184,9 +184,10 @@ async def main() -> None:
- `isolation_level`: level of isolation. Default how it is in PostgreSQL.
- `read_variant`: configure read variant of the transaction. Default how it is in PostgreSQL.
- `deferrable`: configure deferrable of the transaction. Default how it is in PostgreSQL.
- `synchronous_commit`: configure [synchronous_commit](https://postgresqlco.nf/doc/en/param/synchronous_commit/) option for transaction. Default how it is in PostgreSQL.

```python
from psqlpy import IsolationLevel, ReadVariant
from psqlpy import IsolationLevel, ReadVariant, SynchronousCommit

async def main() -> None:
...
Expand All @@ -195,6 +196,7 @@ async def main() -> None:
isolation_level=IsolationLevel.Serializable,
read_variant=ReadVariant.ReadWrite,
deferrable=True,
synchronous_commit=SynchronousCommit.On,
)
```

Expand Down
2 changes: 1 addition & 1 deletion docs/components/connection_pool.md
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ Parameters must be passed as list after querystring.
::: caution
You must use `ConnectionPool.execute` method in high-load production code wisely!
It pulls connection from the pool each time you execute query.
Preferable way to execute statements with [Connection](./../../introduction/components/connection.md) or [Transaction](./../../introduction/components/transaction.md)
Preferable way to execute statements with [Connection](./../components/connection.md) or [Transaction](./../components/transaction.md)
:::

```python
Expand Down
128 changes: 128 additions & 0 deletions docs/faq.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
---
title: Frequently asked questions
---

Here you can find most common questions and problems.

### LIMIT of OFFSET isn't working
The main problem is PostgreSQL expects `LIMIT` and `OFFSET` to be BIGINT type but when you pass python `int` into `parameters` it converts to `INTEGER`.

#### Problem and Solution:
```python
from psqlpy import ConnectionPool
from psqlpy.extra_types import BigInt

# --- Incorrect ---
async def main() -> None:
pool = ConnectionPool()
await pool.execute(
querystring="SELECT * FROM users LIMIT $1 OFFSET $2",
parameters=[10, 100],
)


# --- Correct ---
async def main() -> None:
pool = ConnectionPool()
await pool.execute(
querystring="SELECT * FROM users LIMIT $1 OFFSET $2",
parameters=[BigInt(10), BigInt(100)],
)
```

### WHERE IN clause isn't working
Instead of using `WHERE <field> IN ()` clause you must use `WHERE <field> = ANY()`.

#### Problem and Solution:
```python
from psqlpy import ConnectionPool

# --- Incorrect ---
async def main() -> None:
pool = ConnectionPool()
await pool.execute(
querystring="SELECT * FROM users WHERE id IN ($1)",
parameters=[
(1, 2, 3),
],
)


# --- Correct ---
async def main() -> None:
pool = ConnectionPool()
await pool.execute(
querystring="SELECT * FROM users WHERE id = ANY($1)",
parameters=[
(1, 2, 3),
],
)
```

### Wrong binary data

Example error: `binary data has array element type 1043 (character varying) instead of expected 25 (text)`.

This exception tells you that you use wrong data type and you need to specify types explicitly.

For example, when we want to make `WHERE` clause with `ANY` and string values, we need to use `TextArray`, see example below:

#### Problem and Solution:
```python
from psqlpy import ConnectionPool
from psqlpy.extra_types import TextArray

# --- Incorrect ---
async def main() -> None:
pool = ConnectionPool()
await pool.execute(
querystring="SELECT * FROM users WHERE name = ANY($1)",
parameters=[
["Foo", "Bar", "Cafe"],
],
)


# --- Correct ---
async def main() -> None:
pool = ConnectionPool()
await pool.execute(
querystring="SELECT * FROM users WHERE name = ANY($1)",
parameters=[
TextArray(["Foo", "Bar", "Cafe"]),
],
)
```

### Cannot insert empty ARRAY

To insert empty array use explicit [Array Type](./usage/types/array_types.md).

#### Problem and Solution:
Let's assume that we have table `arr_table` with field `some_array` of `VARCHAR ARRAY` type.
The main problem that we cannot determine the type of the empty sequence passed from Python side.
```python
from psqlpy import ConnectionPool
from psqlpy.extra_types import VarCharArray

# --- Incorrect ---
async def main() -> None:
pool = ConnectionPool()
await pool.execute(
querystring="INSERT INTO arr_table (some_array) VALUES ($1)",
parameters=[
[],
],
)


# --- Correct ---
async def main() -> None:
pool = ConnectionPool()
await pool.execute(
querystring="INSERT INTO arr_table (some_array) VALUES ($1)",
parameters=[
VarCharArray([]),
],
)
```
50 changes: 50 additions & 0 deletions docs/usage/types/array_types.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
---
title: Array Types
---
For type safety and better performance we have predefined array types.

| PSQLPy Array Type | PostgreSQL Array Type |
| :---: | :---: |
| BoolArray | BOOLEAN ARRAY |
| UUIDArray | UUID ARRAY |
| VarCharArray | VarChar ARRAY |
| TextArray | Text ARRAY |
| Int16Array | INT2 ARRAY |
| Int32Array | INT4 ARRAY |
| Int64Array | INT8 ARRAY |
| Float32Array | FLOAT4 ARRAY |
| Float64Array | FLOAT8 ARRAY |
| MoneyArray | MONEY ARRAY |
| IpAddressArray | INET ARRAY |
| JSONBArray | JSONB ARRAY |
| JSONArray | JSON ARRAY |
| DateArray | DATE ARRAY |
| TimeArray | TIME ARRAY |
| DateTimeArray | TIMESTAMP ARRAY |
| DateTimeTZArray | TIMESTAMPTZ ARRAY |
| MacAddr6Array | MACADDR ARRAY |
| MacAddr8Array | MACADDR8 ARRAY |
| NumericArray | NUMERIC ARRAY |
| PointArray | POINT ARRAY |
| BoxArray | BOX ARRAY |
| PathArray | PATH ARRAY |
| LineArray | LINE ARRAY |
| LsegArray | LSEG ARRAY |
| CircleArray | CIRCLE ARRAY |

### Example:

```python
from psqlpy import ConnectionPool
from psqlpy.extra_types import TextArray


async def main() -> None:
pool = ConnectionPool()
result = await pool.execute(
querystring="SELECT * FROM users WHERE id = ANY($1)",
parameters=[
TextArray([1, 2, 3]),
]
)
```
1 change: 1 addition & 0 deletions docs/usage/types/supported_types.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ DECIMAL PostgreSQL type isn't supported, use NUMERIC instead.
## Array Type

You can make arrays with any type of `Simple Type`s.
For better performance and type safety we recommend to use predefined [Array Types](./array_types.md).

#### Example:
```sql
Expand Down
Loading

0 comments on commit 901c644

Please sign in to comment.