Skip to content

Commit 6211f03

Browse files
feat: add PostgreSQL store as async-only implementation
- Add PostgreSQL store using asyncpg for native async operations - Configure as async-only (no sync codegen, following DynamoDB/Memcached pattern) - Add comprehensive documentation in docs/stores.md - Include DuckDB in documentation table as well - Add postgresql extra dependency to pyproject.toml - Exclude PostgreSQL from sync codegen in build_sync_library.py The PostgreSQL store provides: - JSONB storage for flexible key-value data - TTL support via expiration timestamps - Single table design with collections as column values - Async-only implementation using asyncpg Co-authored-by: William Easton <strawgate@users.noreply.github.com>
1 parent 1aa915d commit 6211f03

File tree

8 files changed

+835
-5
lines changed

8 files changed

+835
-5
lines changed

docs/stores.md

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ Local stores are stored in memory or on disk, local to the application.
3434
| Memory | N/A ||| Fast in-memory storage for development and caching |
3535
| Disk | Stable | ☑️ || Persistent file-based storage in a single file |
3636
| Disk (Per-Collection) | Stable | ☑️ || Persistent storage with separate files per collection |
37+
| DuckDB | Unstable | ☑️ || In-process SQL OLAP database with native JSON storage |
3738
| FileTree (test) | Unstable | ☑️ || Directory-based storage with JSON files for visual inspection |
3839
| Null (test) | N/A ||| No-op store for testing without side effects |
3940
| RocksDB | Unstable | ☑️ || High-performance embedded database |
@@ -400,6 +401,7 @@ Distributed stores provide network-based storage for multi-node applications.
400401
| Elasticsearch | Unstable ||| Full-text search with key-value capabilities |
401402
| Memcached | Unstable || ✖️ | High-performance distributed memory cache |
402403
| MongoDB | Unstable ||| Document database used as key-value store |
404+
| PostgreSQL | Unstable || ✖️ | PostgreSQL database with JSONB storage |
403405
| Redis | Stable ||| Popular in-memory data structure store |
404406
| Valkey | Stable ||| Open-source Redis fork |
405407

@@ -569,6 +571,55 @@ pip install py-key-value-aio[mongodb]
569571

570572
---
571573

574+
### PostgreSQLStore
575+
576+
PostgreSQL database with JSONB storage for flexible key-value data.
577+
578+
**Note:** PostgreSQL is async-only. This store uses `asyncpg` which provides native async/await operations.
579+
580+
```python
581+
from key_value.aio.stores.postgresql import PostgreSQLStore
582+
583+
# Using connection URL
584+
store = PostgreSQLStore(url="postgresql://localhost:5432/mydb")
585+
586+
# Using connection parameters
587+
store = PostgreSQLStore(
588+
host="localhost",
589+
port=5432,
590+
database="mydb",
591+
user="myuser",
592+
password="mypass"
593+
)
594+
595+
async with store:
596+
await store.put(key="user_1", value={"name": "Alice"}, collection="users")
597+
user = await store.get(key="user_1", collection="users")
598+
```
599+
600+
**Installation:**
601+
602+
```bash
603+
pip install py-key-value-aio[postgresql]
604+
```
605+
606+
**Use Cases:**
607+
608+
- Applications already using PostgreSQL
609+
- Need for SQL querying on stored data
610+
- ACID transaction requirements
611+
- Complex data relationships
612+
613+
**Characteristics:**
614+
615+
- JSONB storage for efficient querying
616+
- TTL support via expiration timestamps
617+
- Single table design (collections as column values)
618+
- Async-only (uses asyncpg)
619+
- Stable storage format: **Unstable**
620+
621+
---
622+
572623
### MemcachedStore
573624

574625
High-performance distributed memory caching system.

key-value/key-value-aio/pyproject.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ rocksdb = [
5050
"rocksdict>=0.3.2 ; python_version < '3.12'"
5151
]
5252
duckdb = ["duckdb>=1.1.1", "pytz>=2025.2"]
53+
postgresql = ["asyncpg>=0.30.0"]
5354
wrappers-encryption = ["cryptography>=45.0.0"]
5455

5556
[tool.pytest.ini_options]
@@ -69,7 +70,7 @@ env_files = [".env"]
6970

7071
[dependency-groups]
7172
dev = [
72-
"py-key-value-aio[memory,disk,filetree,redis,elasticsearch,memcached,mongodb,vault,dynamodb,rocksdb,duckdb]",
73+
"py-key-value-aio[memory,disk,filetree,redis,elasticsearch,memcached,mongodb,vault,dynamodb,rocksdb,duckdb,postgresql]",
7374
"py-key-value-aio[valkey]; platform_system != 'Windows'",
7475
"py-key-value-aio[keyring]",
7576
"py-key-value-aio[pydantic]",
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
"""PostgreSQL store for py-key-value-aio."""
2+
3+
try:
4+
from key_value.aio.stores.postgresql.store import PostgreSQLStore, PostgreSQLV1CollectionSanitizationStrategy
5+
except ImportError as e:
6+
msg = 'PostgreSQLStore requires the "postgresql" extra. Install via: pip install "py-key-value-aio[postgresql]"'
7+
raise ImportError(msg) from e
8+
9+
__all__ = ["PostgreSQLStore", "PostgreSQLV1CollectionSanitizationStrategy"]

0 commit comments

Comments
 (0)