Skip to content

Commit

Permalink
Fix: Allow ID autoincrement in SQLite (#82)
Browse files Browse the repository at this point in the history
  • Loading branch information
pal03377 authored Aug 19, 2023
1 parent 616cec5 commit 5504838
Show file tree
Hide file tree
Showing 8 changed files with 39 additions and 15 deletions.
16 changes: 16 additions & 0 deletions athena/athena/models/big_integer_with_autoincrement.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
"""
SQLAlchemy + SQLite does not support the autoincrement feature for BigInteger columns.
This file provides a class as a workaround for this problem:
It uses a normal Integer column in SQLite and a BigInteger column otherwise.
SQLite Integer columns can autoincrement, but they are limited to 2^63-1.
See https://stackoverflow.com/a/23175518/4306257 for more information.
"""

from sqlalchemy import BigInteger
from sqlalchemy.dialects import postgresql, mysql, sqlite

# Solution from https://stackoverflow.com/a/23175518/4306257
BigIntegerWithAutoincrement = BigInteger()
BigIntegerWithAutoincrement = BigIntegerWithAutoincrement.with_variant(postgresql.BIGINT(), 'postgresql')
BigIntegerWithAutoincrement = BigIntegerWithAutoincrement.with_variant(mysql.BIGINT(), 'mysql')
BigIntegerWithAutoincrement = BigIntegerWithAutoincrement.with_variant(sqlite.INTEGER(), 'sqlite')
5 changes: 3 additions & 2 deletions athena/athena/models/db_exercise.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
from sqlalchemy import Column, BigInteger, String, Float, JSON, Enum as SqlEnum
from sqlalchemy import Column, String, Float, JSON, Enum as SqlEnum

from athena.schemas import ExerciseType
from .model import Model
from .big_integer_with_autoincrement import BigIntegerWithAutoincrement


class DBExercise(Model):
id = Column(BigInteger, primary_key=True, index=True, nullable=False)
id = Column(BigIntegerWithAutoincrement, primary_key=True, index=True, nullable=False)
title = Column(String, index=True, nullable=False)
type = Column(SqlEnum(ExerciseType), index=True, nullable=False)
max_points = Column(Float, index=True, nullable=False)
Expand Down
3 changes: 2 additions & 1 deletion athena/athena/models/db_feedback.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
from sqlalchemy import Column, BigInteger, Boolean, String, Float, JSON, UniqueConstraint

from .model import Model
from .big_integer_with_autoincrement import BigIntegerWithAutoincrement


class DBFeedback(Model):
__table_args__ = (UniqueConstraint('lms_id'),)

id = Column(BigInteger, primary_key=True, index=True, autoincrement=True)
id = Column(BigIntegerWithAutoincrement, primary_key=True, index=True, autoincrement=True)
lms_id = Column(BigInteger)
title = Column(String)
description = Column(String)
Expand Down
7 changes: 4 additions & 3 deletions athena/athena/models/db_programming_feedback.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
from typing import cast, Optional
from athena.schemas.programming_submission import ProgrammingSubmission
from sqlalchemy import Column, Integer, BigInteger, String, ForeignKey
from sqlalchemy import Column, Integer, String, ForeignKey
from sqlalchemy.orm import relationship

from athena.database import Base, get_db
from .db_programming_submission import DBProgrammingSubmission
from .db_feedback import DBFeedback
from .big_integer_with_autoincrement import BigIntegerWithAutoincrement


class DBProgrammingFeedback(DBFeedback, Base):
Expand All @@ -15,8 +16,8 @@ class DBProgrammingFeedback(DBFeedback, Base):
line_start: Optional[int] = Column(Integer) # type: ignore
line_end: Optional[int] = Column(Integer) # type: ignore

exercise_id = Column(BigInteger, ForeignKey("programming_exercises.id", ondelete="CASCADE"), index=True)
submission_id = Column(BigInteger, ForeignKey("programming_submissions.id", ondelete="CASCADE"), index=True)
exercise_id = Column(BigIntegerWithAutoincrement, ForeignKey("programming_exercises.id", ondelete="CASCADE"), index=True)
submission_id = Column(BigIntegerWithAutoincrement, ForeignKey("programming_submissions.id", ondelete="CASCADE"), index=True)

exercise = relationship("DBProgrammingExercise", back_populates="feedbacks")
submission = relationship("DBProgrammingSubmission", back_populates="feedbacks")
Expand Down
5 changes: 3 additions & 2 deletions athena/athena/models/db_programming_submission.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
from sqlalchemy import ForeignKey, BigInteger, Column, String
from sqlalchemy import ForeignKey, Column, String
from sqlalchemy.orm import relationship

from athena.database import Base
from .db_submission import DBSubmission
from .big_integer_with_autoincrement import BigIntegerWithAutoincrement


class DBProgrammingSubmission(DBSubmission, Base):
__tablename__ = "programming_submissions"
repository_url: str = Column(String, nullable=False) # type: ignore

exercise_id = Column(BigInteger, ForeignKey("programming_exercises.id", ondelete="CASCADE"), index=True)
exercise_id = Column(BigIntegerWithAutoincrement, ForeignKey("programming_exercises.id", ondelete="CASCADE"), index=True)

exercise = relationship("DBProgrammingExercise", back_populates="submissions")
feedbacks = relationship("DBProgrammingFeedback", back_populates="submission")
6 changes: 4 additions & 2 deletions athena/athena/models/db_submission.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from sqlalchemy import Column, BigInteger, JSON
from sqlalchemy import Column, JSON

from .model import Model
from .big_integer_with_autoincrement import BigIntegerWithAutoincrement


class DBSubmission(Model):
id = Column(BigInteger, primary_key=True, index=True, nullable=False)
id = Column(BigIntegerWithAutoincrement, primary_key=True, index=True, autoincrement=True,)
meta = Column(JSON, nullable=False)
7 changes: 4 additions & 3 deletions athena/athena/models/db_text_feedback.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
from typing import Optional

from sqlalchemy import Column, Integer, BigInteger, ForeignKey
from sqlalchemy import Column, Integer, ForeignKey
from sqlalchemy.orm import relationship

from athena.database import Base
from .db_feedback import DBFeedback
from .big_integer_with_autoincrement import BigIntegerWithAutoincrement


class DBTextFeedback(DBFeedback, Base):
Expand All @@ -13,8 +14,8 @@ class DBTextFeedback(DBFeedback, Base):
index_start: Optional[int] = Column(Integer) # type: ignore
index_end: Optional[int] = Column(Integer) # type: ignore

exercise_id = Column(BigInteger, ForeignKey("text_exercises.id", ondelete="CASCADE"), index=True)
submission_id = Column(BigInteger, ForeignKey("text_submissions.id", ondelete="CASCADE"), index=True)
exercise_id = Column(BigIntegerWithAutoincrement, ForeignKey("text_exercises.id", ondelete="CASCADE"), index=True)
submission_id = Column(BigIntegerWithAutoincrement, ForeignKey("text_submissions.id", ondelete="CASCADE"), index=True)

exercise = relationship("DBTextExercise", back_populates="feedbacks")
submission = relationship("DBTextSubmission", back_populates="feedbacks")
5 changes: 3 additions & 2 deletions athena/athena/models/db_text_submission.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
from sqlalchemy import ForeignKey, BigInteger, Column, String
from sqlalchemy import ForeignKey, Column, String
from sqlalchemy.orm import relationship

from athena.database import Base
from .db_submission import DBSubmission
from .big_integer_with_autoincrement import BigIntegerWithAutoincrement


class DBTextSubmission(DBSubmission, Base):
__tablename__ = "text_submissions"
text: str = Column(String, nullable=False) # type: ignore
language: str = Column(String, nullable=True) # type: ignore

exercise_id = Column(BigInteger, ForeignKey("text_exercises.id", ondelete="CASCADE"), index=True)
exercise_id = Column(BigIntegerWithAutoincrement, ForeignKey("text_exercises.id", ondelete="CASCADE"), index=True)

exercise = relationship("DBTextExercise", back_populates="submissions")
feedbacks = relationship("DBTextFeedback", back_populates="submission")

0 comments on commit 5504838

Please sign in to comment.