Вопрос

Here's my ORM entity class. The primary key is composite cause 'id_string' may be the same for different users (identified by uid). One thing I understood from Postgres SQL error when creating a table based on this class (

ProgrammingError: (ProgrammingError) there is no unique constraint matching given keys for referenced table "sync_entities"

) is that I need to add something to parent_id_string's ForeignKey() argument. And that something is, I think, the current record's uid.

Do you suggest to try using different primary key (autoincrementing integer) or there is some other way?

class SyncEntity(Base):
    __tablename__ = 'sync_entities'
    __table_args__ = (ForeignKeyConstraint(['uid'], ['users.uid'], ondelete='CASCADE'), {})

    uid = Column(BigInteger, primary_key=True)

    id_string = Column(String, primary_key=True)
    parent_id_string = Column(String, ForeignKey('sync_entities.id_string'))
    children = relation('SyncEntity',
                        primaryjoin=('sync_entities.c.id_string==sync_entities.c.parent_id_string'),
                        backref=backref('parent', \
                                        remote_side=[id_string]))

    # old_parent_id = ...
    version = Column(BigInteger)
    mtime = Column(BigInteger)
    ctime = Column(BigInteger)
    name = Column(String)
    non_unique_name = Column(String)
    sync_timestamp = Column(BigInteger)
    server_defined_unique_tag = Column(String)
    position_in_parent = Column(BigInteger)

    insert_after_item_id = Column(String, ForeignKey('sync_entities.id_string'))
    insert_after = relation('SyncEntity',
                            primaryjoin=('sync_entities.c.id_string==sync_entities.c.insert_after_item_id'),
                            remote_side=[id_string])

    deleted = Column(Boolean)
    originator_cache_guid = Column(String)
    originator_client_item_id = Column(String)
    specifics = Column(LargeBinary)
    folder = Column(Boolean)
    client_defined_unique_tag = Column(String)
    ordinal_in_parent = Column(LargeBinary)
Это было полезно?

Решение

You know, primary key being an auto-incremented integer is usually the best approach. Any values that seem to be unique in system, may turn out to be duplicated in future. If you relied on their uniqueness you're in deep trouble.

However, if there is a reason to require certain pair (or triple) of values in each row to be unique, just add constraint to your table, but use auto-increment integer as primary key. Then if requirements change, you can alter/remove/relax your unique constraint without making changes elsewhere.

Also - if you're using simple integer keys, your joins are simpler and can be performed faster by DBMS.

Другие советы

I think I came up with a good idea. Just need to create complex foreign key constructs in the __tableargs__ member like (parent_id_string, uid) and (insert_after_item_id, uid), modifying the primaryjoin statements accordingly.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top