I have a Django-created tables in PostgreSQL 8.4 database, where one table “extends” another. One table (FooPayment) has primary key, which references another table (Payment). In SQL it looks like this:
CREATE TABLE foo.payments_payment
(
id integer NOT NULL DEFAULT nextval('payments_payment_id_seq'::regclass),
user_id integer NOT NULL,
...
CONSTRAINT payments_payment_pkey PRIMARY KEY (id),
CONSTRAINT payments_payment_user_id_fkey FOREIGN KEY (user_id)
REFERENCES auth.auth_user (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION DEFERRABLE INITIALLY DEFERRED
)
CREATE TABLE foo.payments_foopayment
(
payment_ptr_id integer NOT NULL,
...
CONSTRAINT payments_foopayment_pkey PRIMARY KEY (payment_ptr_id),
CONSTRAINT payments_foopayment_payment_ptr_id_fkey FOREIGN KEY (payment_ptr_id)
REFERENCES foo.payments_payment (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION DEFERRABLE INITIALLY DEFERRED,
...
)
However, I’ve not to use Django ORM for various reasons, and I’m trying to access the tables from SQLAlchemy (I’m using version 0.6.6, as was installed with pip):
# Base = declarative_base()
...
class Payment(Base):
__tablename__ = 'payments_payment'
__table_args__ = {'schema': 'foo', 'autoload': True}
user = relation(User, backref='payments')
class FooPayment(Payment):
__tablename__ = 'payments_foopayment'
__table_args__ = {'schema': 'foo', 'autoload': True}
When I’m doing this as superuser, everything works. When I’m connecting as low-privileged user I get an exception:
Traceback (most recent call last):
File "./test.py", line 3, in <module>
from foos import models
File "./foos/models.py", line 127, in <module>
class FooPayment(Payment):
File "lib/python2.6/site-packages/sqlalchemy/ext/declarative.py", line 1167, in __init__
_as_declarative(cls, classname, cls.__dict__)
File "lib/python2.6/site-packages/sqlalchemy/ext/declarative.py", line 1099, in _as_declarative
ignore_nonexistent_tables=True)
File "lib/python2.6/site-packages/sqlalchemy/sql/util.py", line 260, in join_condition
"between '%s' and '%s'.%s" % (a.description, b.description, hint))
sqlalchemy.exc.ArgumentError: Can't find any foreign key relationships between 'payments_payment' and 'payments_foopayment'.
When I’m connecting as this low-privileged user with PgAdmin3, I see the relationship in GUI. I can also see it with this statement, SQLAlchemy issues itself:
SELECT conname, pg_catalog.pg_get_constraintdef(oid, true) as condef
FROM pg_catalog.pg_constraint r
WHERE r.conrelid = 16234 AND r.contype = 'f'
ORDER BY 1
Which properly returns a row, containing
"payments_foopayment_payment_ptr_id_fkey"; "FOREIGN KEY (payment_ptr_id) REFERENCES payments_payment(id) DEFERRABLE INITIALLY DEFERRED"
As for database permissions, both payments_payment and payments_foopayment are GRANTed SELECT and UPDATE. I’ve tried temporarily granting all permissions on them, without any success. If this matters, a seqence payments_payment_id_seq is GRANTed for SELECT and USAGE. Obviously, schema foo is GRANTed for USAGE.
How should I either define the relationship manually in Python, or do something on DB side, so introspection would work for non-privileged user?
Hints on debugging the problem are also very much welcomed, as I’m completely lost in SA internals.
You can log the queries of SQLAlchemy, and compare what happens with different users.
logging.DEBUGlogs the response data as well.As far as I can tell, for reflection, SQLAlchemy uses table OIDs and queries pg_catalog; you gave an example. The code is in
SQLAlchemy.dialects.postgresql.base.If the permissions for autoload give you grief, you can declare the relationship in code with something like this: