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:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user