Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SQLAlchemy index causes "Can't add unnamed column to column collection" if an abstract table is involved

I have a base "abstract" table and an "entity" table that inherits the abstract columns and adds its own:

class AbstractTable(Base):
    __abstract__ = True
    id = Column(Integer, autoincrement=True, primary_key=True)
    name = Column(Unicode)
    value = Column(Unicode)


class EntityTable(AbstractTable):
    entity_id = Column(Integer)
    __table_args__ = ()

I need a unique composite index on entity_id and name. To the __table_args__, I add:

Index('entity_id_name', entity_id, AbstractTable.name, unique=True)

Once this is added, I receive the following stack trace:

Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "[...]/lib/python2.7/site-packages/flask_sqlalchemy/__init__.py", line 609, in __init__
    DeclarativeMeta.__init__(self, name, bases, d)
  File "[...]/lib/python2.7/site-packages/sqlalchemy/ext/declarative/api.py", line 64, in __init__
    _as_declarative(cls, classname, cls.__dict__)
  File "[...]/lib/python2.7/site-packages/sqlalchemy/ext/declarative/base.py", line 88, in _as_declarative
    _MapperConfig.setup_mapping(cls, classname, dict_)
  File "[...]/lib/python2.7/site-packages/sqlalchemy/ext/declarative/base.py", line 103, in setup_mapping
    cfg_cls(cls_, classname, dict_)
  File "[...]/lib/python2.7/site-packages/sqlalchemy/ext/declarative/base.py", line 131, in __init__
    self._setup_table()
  File "[...]/lib/python2.7/site-packages/sqlalchemy/ext/declarative/base.py", line 395, in _setup_table
    **table_kw)
  File "[...]/lib/python2.7/site-packages/sqlalchemy/sql/schema.py", line 439, in __new__
    metadata._remove_table(name, schema)
  File "[...]/lib/python2.7/site-packages/sqlalchemy/util/langhelpers.py", line 66, in __exit__
    compat.reraise(exc_type, exc_value, exc_tb)
  File "[...]/lib/python2.7/site-packages/sqlalchemy/sql/schema.py", line 434, in __new__
    table._init(name, metadata, *args, **kw)
  File "[...]/lib/python2.7/site-packages/sqlalchemy/sql/schema.py", line 518, in _init
    self._init_items(*args)
  File "[...]/lib/python2.7/site-packages/sqlalchemy/sql/schema.py", line 79, in _init_items
    item._set_parent_with_dispatch(self)
  File "[...]/lib/python2.7/site-packages/sqlalchemy/sql/base.py", line 431, in _set_parent_with_dispatch
    self._set_parent(parent)
  File "[...]/lib/python2.7/site-packages/sqlalchemy/sql/schema.py", line 3367, in _set_parent
    ColumnCollectionMixin._set_parent(self, table)
  File "[...]/lib/python2.7/site-packages/sqlalchemy/sql/schema.py", line 2611, in _set_parent
    self.columns.add(col)
  File "[...]/lib/python2.7/site-packages/sqlalchemy/sql/base.py", line 503, in add
    "Can't add unnamed column to column collection")
ArgumentError: Can't add unnamed column to column collection

Clearly it doesn't like that, although as best I can figure this should work as written.

I can silence the error if I change AbstractTable.name in the index definition to the string 'name', like:

Index('entity_id_name', entity_id, 'name', unique=True)

... but I've never had to use string column names in an index before. Am I incorrect in thinking that I should be able to reference the abstract columns in this way?

like image 885
smitelli Avatar asked Dec 09 '25 10:12

smitelli


1 Answers

Yes to being incorrect. Inheritance in case of abstract declarative base classes works so that it creates copies of found Columns from the parent to child. Add to that that the columns in an abstract base class aren't initialized in the same fashion as in concrete classes. So you're referencing the wrong class' uninitialized column. Either define the column as a string, or define the Index externally after the EntityTable class, as described here.

class EntityTable(AbstractTable):
    ...

# The class has been constructed and has usable columns.
Index('entity_id_name', EntityTable.entity_id, EntityTable.name, unique=True)
like image 166
Ilja Everilä Avatar answered Dec 10 '25 22:12

Ilja Everilä