Skip to content

Commit 26cf123

Browse files
committed
feat: postgres setup
1 parent 93ae309 commit 26cf123

19 files changed

Lines changed: 99 additions & 34 deletions

docker-compose.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,16 @@ services:
1313
interval: 5s
1414
timeout: 5s
1515
retries: 10
16+
postgres:
17+
image: postgres:17
18+
environment:
19+
POSTGRES_DB: database_app_test
20+
POSTGRES_USER: app
21+
POSTGRES_PASSWORD: secret
22+
ports:
23+
- "5432:5432"
24+
healthcheck:
25+
test: [ "CMD", "pg_isready", "-U", "app", "-d", "database_app_test" ]
26+
interval: 5s
27+
timeout: 5s
28+
retries: 10

fastapi_startkit/src/fastapi_startkit/masoniteorm/connections/manager.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ def get_schema_builder(self):
3939

4040
return Schema(self)
4141

42-
def clear(self):
42+
async def clear(self):
4343
for conn in self.connections.values():
44-
conn.engine.dispose()
44+
await conn.engine.dispose()
4545
self.connections.clear()

fastapi_startkit/src/fastapi_startkit/masoniteorm/connections/postgres_connection.py

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import Any
1+
from sqlalchemy import text
22
from fastapi_startkit.masoniteorm.query.grammars import PostgresGrammar
33
from fastapi_startkit.masoniteorm.query.processors import PostgresPostProcessor
44
from fastapi_startkit.masoniteorm.schema.platforms import PostgresPlatform
@@ -20,18 +20,20 @@ def get_default_platform(cls):
2020
def get_post_processor(cls):
2121
return PostgresPostProcessor
2222

23-
async def insert(self, query: str, bindings: list | None = None) -> Any:
24-
"""Postgres uses RETURNING to get the inserted id/row."""
25-
query, params = self.sql_alchemy_bindings(query, bindings)
23+
async def insert(self, query: str, bindings: list | None = None) -> int | None:
24+
"""Execute an INSERT ... RETURNING * and return the generated primary key."""
25+
query_str, params = self.sql_alchemy_bindings(query, bindings)
26+
conn = await self.get_connection()
27+
result = await conn.execute(text(query_str), params or {})
2628

27-
from sqlalchemy import text
28-
29-
async with self.engine.connect() as conn:
30-
result = await conn.execute(text(query), params)
29+
if not self.transactions:
3130
await conn.commit()
3231

33-
row = result.fetchone()
34-
if row:
35-
return dict(zip(result.keys(), row))
32+
row = result.fetchone()
33+
if row:
34+
return row[0]
3635

37-
return None
36+
# Fallback for cases where RETURNING result is unavailable
37+
val_result = await conn.execute(text("SELECT lastval()"))
38+
val_row = val_result.fetchone()
39+
return val_row[0] if val_row else None

fastapi_startkit/tests/masoniteorm/fixtures/migration.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
1-
from .db import DB
1+
from fastapi_startkit.masoniteorm.schema import Schema
22

3-
schema = DB.get_schema_builder()
43

5-
6-
async def wipe():
4+
async def wipe(schema: Schema) -> None:
75
for connection in ("default", "dev"):
86
tables = await schema.on(connection).get_all_tables()
97
for table in tables:
108
await schema.on(connection).drop_table_if_exists(table)
119

1210

13-
async def migrate():
11+
async def migrate(schema: Schema) -> None:
1412
async with await schema.on("default").create_table_if_not_exists("users") as table:
1513
table.id()
1614
table.string("name")

fastapi_startkit/tests/masoniteorm/postgres/__init__.py

Whitespace-only changes.

fastapi_startkit/tests/masoniteorm/postgres/fixtures/__init__.py

Whitespace-only changes.
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
from fastapi_startkit.masoniteorm.connections.factory import ConnectionFactory
2+
from fastapi_startkit.masoniteorm.connections.manager import DatabaseManager
3+
4+
URL = "postgresql+asyncpg://app:secret@localhost:5432/database_app_test"
5+
6+
DB = DatabaseManager(
7+
ConnectionFactory(),
8+
{
9+
"default": "postgres",
10+
"connections": {
11+
"postgres": {
12+
"driver": "postgres",
13+
"url": URL,
14+
"database": "database_app_test",
15+
},
16+
"dev": {
17+
"driver": "postgres",
18+
"url": URL,
19+
"database": "database_app_test",
20+
},
21+
},
22+
},
23+
)
24+
25+
schema = DB.get_schema_builder()

fastapi_startkit/tests/masoniteorm/postgres/models/__init__.py

Whitespace-only changes.
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
from unittest import IsolatedAsyncioTestCase
2+
3+
from fastapi_startkit.masoniteorm.models.model import Model
4+
from fastapi_startkit.masoniteorm.testing.transaction import RefreshDatabase
5+
from ..fixtures.db import DB, schema
6+
from ...fixtures.migration import migrate, wipe
7+
from ...fixtures.model import User
8+
9+
10+
class TestPostGresModel(RefreshDatabase, IsolatedAsyncioTestCase):
11+
async def asyncSetUp(self):
12+
Model.db_manager = DB
13+
await DB.clear()
14+
await wipe(schema)
15+
await migrate(schema)
16+
17+
async def asyncTearDown(self):
18+
await wipe(schema)
19+
await DB.clear()
20+
21+
async def test_can_create_and_find_user(self):
22+
user = await User.create({"name": "Alice", "email": "alice@example.com", "is_admin": False})
23+
self.assertIsNotNone(user.id)
24+
25+
found = await User.find(user.id)
26+
self.assertEqual(found.name, "Alice")
27+
self.assertEqual(found.email, "alice@example.com")

fastapi_startkit/tests/masoniteorm/sqlite/builder/test_sqlite_builder_insert.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from unittest.mock import AsyncMock
22

3-
from ...fixtures.db import DB
3+
from ..fixtures.db import DB
44
from ...fixtures.model import User
55
from ..test_case import TestCase
66

0 commit comments

Comments
 (0)