kvesteri / sqlalchemy-continuum

Versioning extension for SQLAlchemy.
BSD 3-Clause "New" or "Revised" License
580 stars 126 forks source link

Oracle - fails when modifying relations using association tables #289

Closed AbdealiLoKo closed 2 years ago

AbdealiLoKo commented 2 years ago

I have a scenario where we have:

Reproducibel code:

from sqlalchemy import Column, ForeignKey, Identity, Integer, String, Table, create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import configure_mappers, relationship, sessionmaker
from sqlalchemy_continuum import make_versioned

make_versioned(user_cls=None)
Base = declarative_base()

class BaseModel(Base):
    __abstract__ = True

    def __repr__(self):
        return super().__repr__() + f" ({self.name})"

book_author = Table(
    "book_author",
    Base.metadata,
    Column("author_id", ForeignKey("author.id"), primary_key=True),
    Column("book_id", ForeignKey("book.id"), primary_key=True),
)

class Author(BaseModel):
    __tablename__ = "author"
    __versioned__ = {}
    id = Column(Integer, Identity(), primary_key=True)
    name = Column(String(255))

    books = relationship("Book", secondary=book_author, back_populates="authors", lazy='selectin')

class Book(BaseModel):
    __tablename__ = "book"
    __versioned__ = {}
    id = Column(Integer, Identity(), primary_key=True)
    name = Column(String(255))

    authors = relationship("Author", secondary=book_author, back_populates="books", lazy='selectin')

configure_mappers()
engine = create_engine('oracle://user:pass@host/dbname', echo=True)

# Create session
session = sessionmaker()
session.configure(bind=engine)

# Create all models we need
Base.metadata.create_all(engine)

db = session()

adams = Author(name='Douglas Adams')
h2g2 = Book(name='h2g2', authors=[adams])
db.add(adams)
db.add(h2g2)

db.commit()

The relevant part of the error is:

INSERT INTO book_author (author_id, book_id) VALUES (:author_id, :book_id)
[generated in 0.00093s] {'author_id': 1, 'book_id': 1, 'operation_type': 0}

sqlalchemy.exc.DatabaseError: (cx_Oracle.DatabaseError) ORA-01036: illegal variable name/number

It looks like sqla-continuum is adding operation_type to the params of the original query in book_author I was expecting it to only add it in book_author_version

marksteward commented 2 years ago

Fixed by #291