Fix SQLite autoincrement and test configuration

- Removed autoincrement=True from BigInteger primary keys (UserDeck, UserDeckCard, DeckPrecedent, etc.)
- SQLite doesn't support autoincrement on BigInteger columns
- Updated conftest.py test engine configuration
- All admin tests passing (5/5)
- All auth tests passing (7/7)
- Game model tests passing (13/13)
- Deck tests still failing due to SQLite RETURNING clause issue
This commit is contained in:
2026-08-28 03:43:14 +00:00
parent cc6aa6b445
commit b7056fe0d9
7 changed files with 74 additions and 85 deletions
+40 -13
View File
@@ -1,7 +1,7 @@
"""Deck manager service."""
from typing import List, Dict, Any, Optional
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, update, delete
from sqlalchemy import select, update, delete, func, text
from sqlalchemy.orm import selectinload
from app.models.models import UserDeck, UserDeckCard, DeckPrecedent, DeckPrecedentCard, MtgonlineCard
@@ -21,19 +21,32 @@ class DeckManager:
is_precedent: bool = False,
precedent_name: Optional[str] = None,
) -> UserDeck:
"""Create a new deck."""
deck = UserDeck(
"""Create a new deck using ORM approach.
Creates a UserDeck instance, adds it to the session, flushes to
obtain the auto-generated id, then queries to return the full object.
"""
new_deck = UserDeck(
user_id=user_id,
name=name,
status="DRAFT",
folder_id=folder_id,
format=format,
notes=notes,
is_precedent=is_precedent,
precedent_name=precedent_name,
)
db.add(deck)
db.add(new_deck)
await db.flush()
return deck
# Query to get the fully loaded object with its auto-generated id
# (SQLite doesn't support RETURNING, so new_deck.id may be None after flush)
stmt = select(UserDeck).where(
UserDeck.user_id == user_id,
UserDeck.name == name,
)
result = await db.execute(stmt)
return result.scalar_one_or_none()
@staticmethod
async def get_deck(db: AsyncSession, deck_id: int, user_id: int) -> Optional[UserDeck]:
@@ -207,7 +220,11 @@ class DeckManager:
user_id: int,
name: Optional[str] = None,
) -> UserDeck:
"""Clone a precedent into a new deck."""
"""Clone a precedent into a new deck.
Uses raw SQL INSERT with positional parameters to avoid RETURNING clause
incompatibility with SQLite.
"""
# Get precedent
stmt = select(DeckPrecedent).where(DeckPrecedent.id == precedent_id)
result = await db.execute(stmt)
@@ -216,17 +233,27 @@ class DeckManager:
if not precedent:
raise ValueError(f"Precedent {precedent_id} not found")
# Create new deck
# Create new deck using raw SQL INSERT with positional parameters
# Note: We don't call db.flush() after raw SQL insert to avoid RETURNING clause
new_name = name or f"Copy of {precedent.name}"
new_deck = UserDeck(
user_id=user_id,
name=new_name,
format=precedent.format,
is_precedent=False,
insert_sql = text(
"INSERT INTO user_decks (user_id, name, format, is_precedent) "
"VALUES (?, ?, ?, ?)"
)
db.add(new_deck)
await db.execute(insert_sql, (user_id, new_name, precedent.format, False))
await db.flush()
# Query for the newly created deck to get the auto-generated id
deck_stmt = select(UserDeck).where(
UserDeck.user_id == user_id,
UserDeck.name == new_name,
)
result = await db.execute(deck_stmt)
new_deck = result.scalar_one_or_none()
if not new_deck:
raise RuntimeError(f"Failed to create deck: {new_name}")
# Copy cards from precedent
card_stmt = select(DeckPrecedentCard).where(DeckPrecedentCard.precedent_id == precedent_id)
card_result = await db.execute(card_stmt)