Hello -

I've reproduced your code fragments as a complete MCVE, it runs fine.
Please run this script and try to see where your own application
differs.

from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.ext.declarative import declared_attr

from uuid import uuid4 as function_to_generate_uuid
import uuid


class UUID(TypeDecorator):
    impl = CHAR

    def process_bind_param(self, value, dialect):
        if value is None:
            return value
        else:
            if not isinstance(value, uuid.UUID):
                return "%.32x" % uuid.UUID(value).int
            else:
                # hexstring
                return "%.32x" % value.int

    def process_result_value(self, value, dialect):
        if value is None:
            return value
        else:
            if not isinstance(value, uuid.UUID):
                value = uuid.UUID(value)
            return value

Base = declarative_base()


class EmployeeType(Base):
    __tablename__ = 'employee_types'

    emp_type = Column(String(50), primary_key=True)
    emp_type_description = Column(Text)


class Employee(Base):

    __tablename__ = 'employees'

    emp_id = Column(UUID, primary_key=True)
    emp_type = Column(String(50), ForeignKey(EmployeeType.emp_type))

    emp_groups = relationship("EmployeeMembership", backref='employee')

    __mapper_args__ = {
        'polymorphic_on': emp_type
    }


class EmployeeMembership(Base):
    __tablename__ = 'employee_membership'

    emp_id = Column(UUID, ForeignKey(Employee.emp_id), primary_key=True)
    group = Column(String(25), primary_key=True)


class Engineer(Employee):
    __tablename__ = 'engineers'

    emp_id = Column(UUID, ForeignKey(Employee.emp_id), primary_key=True)

    emp_name = Column(String(50), unique=True, nullable=False)

    engineer_attr = Column(Text)

    __mapper_args__ = {
        'polymorphic_identity': 'engineer'
    }

    # create a new UUID if I don't give one (new Engineer/Employee)
    def __init__(self, *args, **kwargs):
        if 'emp_id' not in kwargs:
            self.emp_id = function_to_generate_uuid()

        super(Engineer,self).__init__(*args, **kwargs)

class Manager(Employee):
    __tablename__ = 'manager'

    emp_id = Column(UUID, ForeignKey(Employee.emp_id), primary_key=True)

    emp_name = Column(String(50), unique=True, nullable=False)

    manager_blah = Column(Text)

    __mapper_args__ = {
        'polymorphic_identity': 'manager'
    }

    # create a new UUID if I don't give one (new Manager/Employee)
    def __init__(self, *args, **kwargs):
        if 'emp_id' not in kwargs:
            self.emp_id = function_to_generate_uuid()

        super(Manager, self).__init__(*args, **kwargs)

e = create_engine("sqlite://", echo=True)
Base.metadata.create_all(e)

s = Session(e)
s.add_all([EmployeeType(emp_type='engineer'), EmployeeType(emp_type='manager')])
s.commit()

new_emp = Engineer(emp_name='Leeroy Jenkins')
session = Session(e)
session.add(new_emp)
session.commit()




output, after create tables and initial setup:

BEGIN (implicit)
2018-03-20 11:34:39,588 INFO sqlalchemy.engine.base.Engine INSERT INTO
employees (emp_id, emp_type) VALUES (?, ?)
2018-03-20 11:34:39,589 INFO sqlalchemy.engine.base.Engine
('8717f41097d140b28a6f46842e774279', 'engineer')
2018-03-20 11:34:39,590 INFO sqlalchemy.engine.base.Engine INSERT INTO
engineers (emp_id, emp_name, engineer_attr) VALUES (?, ?, ?)
2018-03-20 11:34:39,590 INFO sqlalchemy.engine.base.Engine
('8717f41097d140b28a6f46842e774279', 'Leeroy Jenkins', None)
2018-03-20 11:34:39,590 INFO sqlalchemy.engine.base.Engine COMMIT

On Mon, Mar 19, 2018 at 11:04 PM, Peter Lai <cowb...@gmail.com> wrote:
> As seen at:
> https://stackoverflow.com/questions/49374458/how-to-propagate-subclass-primary-key-to-base-class-primary-key-when-creating-ne
>
> I'm running into a problem where I am using joined table inheritance where
> the base class carries "upstream" relationships:
>
> class EmployeeType(Base):
>     __tablename__ = 'employee_types'
>
>     emp_type = Column(String(50), primary_key=True)
>     emp_type_description = Column(Text)
>     # we want to constrain the EmployeeTypes
>
> # UUID is a custom TypeDecorator that generates a UUID correctly for all
> backends
>
> class Employee(Base):
>
>     __tablename__ = 'employees'
>
>     emp_id = Column(UUID, primary_key=True)
>     emp_type = Column(String(50), ForeignKey(EmployeeType.emp_type))
>
>     emp_groups = relationship(EmployeeMembership, backref='employee')
>
>     __mapper_args__ = {
>         'polymorphic_on': emp_type
>     }
>
> # this is a one-to-many association membership-type of object
> class EmployeeMembership(Base):
>     __tablename__ = 'employee_membership'
>
>     emp_id = Column(UUID, ForeignKey(Employee.emp_id), primary_key=True)
>     group = Column(String(25), primary_key=True)
>
>
> class Engineer(Employee):
>     __tablename__ = 'engineers'
>
>     emp_id = Column(UUID, ForeignKey(Employee.emp_id), primary_key=True)
>
>     # emp_name belongs to subclass because within the subclass it needs to
> be unique, but not unique across subclasses
>     # There can be 2 different employees (emp_id are different) named
> 'Leeroy Jenkins' one is a manager and one is an engineer.
>
>     emp_name = Column(String(50), unique=True, nullable=False)
>
>     engineer_attr = Column(Text)
>
>     __mapper_args__ = {
>         'polymorphic_identity': 'engineer'
>     }
>
>     # create a new UUID if I don't give one (new Engineer/Employee)
>     def __init__(self, *args, **kwargs):
>         if 'emp_id' not in kwargs:
>             self.emp_id = function_to_generate_uuid()
>
>         super(Engineer,self).__init__(*args, **kwargs))
>
> class Manager(Employee):
>     __tablename__ = 'manager'
>
>     emp_id = Column(UUID, ForeignKey(Employee.emp_id), primary_key=True)
>
>     # emp_name belongs to subclass because within the subclass it needs to
> be unique, but not unique across subclasses
>     # There can be 2 different employees (emp_id are different) named
> 'Leeroy Jenkins' one is a manager and one is an engineer.
>     emp_name = Column(String(50), unique=True, nullable=False)
>
>     manager_blah = Column(Text)
>
>     __mapper_args__ = {
>         'polymorphic_identity': 'manager'
>     }
>
>     # create a new UUID if I don't give one (new Manager/Employee)
>     def __init__(self, *args, **kwargs):
>         if 'emp_id' not in kwargs:
>             self.emp_id = function_to_generate_uuid()
>
>         super(Manager, self).__init__(*args, **kwargs))
>
>
> The problem is when I go to create either an Engineer or Manager:
>
> new_emp = Engineer(emp_name='Leeroy Jenkins')
> session = Session()
> session.add(new_emp)
> session.commit()
>
>
> I get:
>
> python27\lib\site-packages\sqlalchemy\sql\crud.py:692: SAWarning: Column
> 'employees.emp_id'
> is marked as a member of the primary key for table 'employees', but has no
> Python-side
> or server-side default generator indicated, nor does it indicate
> 'autoincrement=True'
> or 'nullable=True', and no explicit value is passed.  Primary key columns
> typically may not
> store NULL.
> util.warn(msg)
> (psycopg2.IntegrityError) null value in column "emp_id" violates not-null
> constraint
> DETAIL:  Failing row contains (null, engineer).
> [SQL: 'INSERT INTO employees (emp_type) VALUES (%(emp_type)s)'] [parameters:
> {'emp_type': u'engineer'}]
>
>
> What do I need to do to get my instance of base class created properly when
> I create my subclass? I'm still on SQLAlchemy 1.1.13 and py27
>
> Thanks
>
> --
> SQLAlchemy -
> The Python SQL Toolkit and Object Relational Mapper
>
> http://www.sqlalchemy.org/
>
> To post example code, please provide an MCVE: Minimal, Complete, and
> Verifiable Example. See http://stackoverflow.com/help/mcve for a full
> description.
> ---
> You received this message because you are subscribed to the Google Groups
> "sqlalchemy" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to sqlalchemy+unsubscr...@googlegroups.com.
> To post to this group, send email to sqlalchemy@googlegroups.com.
> Visit this group at https://groups.google.com/group/sqlalchemy.
> For more options, visit https://groups.google.com/d/optout.

-- 
SQLAlchemy - 
The Python SQL Toolkit and Object Relational Mapper

http://www.sqlalchemy.org/

To post example code, please provide an MCVE: Minimal, Complete, and Verifiable 
Example.  See  http://stackoverflow.com/help/mcve for a full description.
--- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at https://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.

Reply via email to