Devlog

[MySQL, SQLAlchemy] Error 1170 본문

project.log/Microcloudchip.log

[MySQL, SQLAlchemy] Error 1170

recoma 2022. 7. 21. 18:46
728x90

 

GitHub - SweetCase-Cobalto/cloudmodular: NAS Cloud Hosting Service Application [구현중]

NAS Cloud Hosting Service Application [구현중]. Contribute to SweetCase-Cobalto/cloudmodular development by creating an account on GitHub.

github.com

CloudModular는 Nextcloud 처럼 사용자가 직접 자신의 개인 서버에 설치해서 사용하는 클라우드 서비스 프로젝트 입니다. microcloudchip.log는 해당 프로젝트를 진행하면서 배웠거나 깨달은 부분을 일기처럼 적는 카테고리로 일부 틀린 내용이 있을 수 있습니다. 해당 카테고리에 등록된 포스트들 중 일부는 추가적인 학습 후, 
프로그래밍 관련 카테고리
에 해당 주제와 관련해서 포스팅이 됩니다.

TMI: Nextcloud는 PHP로 구현되어있습니다. 반면에 CloudModular는 FastAPI와 ReactJS로 구현되고 있습니다.
E       sqlalchemy.exc.OperationalError: (MySQLdb._exceptions.OperationalError) (1170, "BLOB/TEXT column 'root' used in key specification without a key length")
E       [SQL:
E       CREATE TABLE datainfo (
E               id INTEGER NOT NULL AUTO_INCREMENT,
E               root TEXT(65535) NOT NULL,
E               name VARCHAR(255) NOT NULL,
E               is_dir BOOL NOT NULL,
E               created DATETIME DEFAULT now(),
E               is_favorite BOOL,
E               user_id INTEGER,
E               PRIMARY KEY (id),
E               UNIQUE (root, name, is_dir),
E               FOREIGN KEY(user_id) REFERENCES user (id) ON DELETE CASCADE ON UPDATE CASCADE
E       )
E
E       ]
E       (Background on this error at: https://sqlalche.me/e/14/e3q8)

Text또는 Blob Type의 Column에 Key를 설정하면 1170 에러가 발생한다. 여기서는 root가 Text Type임에도 불구하고 Unique Key로 잡아놓았기 때문에 테이블 생성을 할 수 없었던 것이다. 하긴 용량이 큰 값을 Key로 두면 이거대로 성능에 문제가 생기기 때문에 이런 부분은 이해한다. 그래서 나는 SQLAlchemy의 Model 선언 부분에서 결국 Unique부분을 주석처리했다.

class DataInfo(Base):
    __tablename__ = 'datainfo'
    """
    TODO root key에 대한 해결 필요
    __table_args__ = (
        UniqueConstraint('root', 'name', 'is_dir'),
    )
    """

    id = Column(Integer, primary_key=True, autoincrement=True)
    root = Column(Text(65535), nullable=False)
    name = Column(String(255), nullable=False)
    is_dir = Column(Boolean, nullable=False)
    created = Column(DateTime(timezone=True), server_default=func.now())
    is_favorite = Column(Boolean, nullable=True, default=False)

    user_id = Column(Integer, ForeignKey('user.id', ondelete='CASCADE', onupdate='CASCADE'))
    user = relationship('User', backref=backref('user', cascade='delete'))

Root가 디렉토리 주소를 의미하는데 String으로 잡기에는 길이나 너무 짧다. 다른 방법으론 자기 자신을 Parent로 잡아서 1대다로 만들 수 있긴 한데 그렇게 되면 검색 쿼리에서 Recursive한 검색을 시도하려고 하면 최악의 경우 수백개의 부모 레코드를 거쳐야 하기 때문에 성능이 하락되는 것으로 예상된다.

그래서 일단 주석 처리를 해두었다. 중복되는 값이 들어갈 위험이 있긴 하지만 이 프로젝트에서 DataInfo에 레코드를 다이렉트하게 추가하기 전에 디렉토리 주소와 이름이 일치하는 지 검토하기 때문에, 당장은 큰 문제가 없어 보인다. 하지만 혹시 DB를 직접 접근하는 경우도 있을 수 있기 때문에(언젠간) 이에 대한 대처도 미리 마련해 둬야 하지 않을듯 싶다.

신기한건 SQLite도 Text 타입이 있긴 한데 저런 오류는 뜨지 않는다.

728x90
반응형

'project.log > Microcloudchip.log' 카테고리의 다른 글

[SQLAlchemy] join함수 사용기  (0) 2022.07.18