Чтобы ответить на мой собственный вопрос, DDL
принимает словарь context
, который применяется к оператору SQL.Это исправленный код:
event.listen(primary_table, 'after_create',
DDL('''
CREATE FUNCTION %(function)s() RETURNS TRIGGER AS $$
DECLARE
target RECORD;
BEGIN
IF (NEW.%(rhs)s IS NOT NULL) THEN
SELECT %(parentcol)s INTO target FROM %(child_table_name)s WHERE %(child_id_column)s = NEW.%(rhs)s;
IF (target.%(parentcol)s != NEW.%(lhs)s) THEN
RAISE foreign_key_violation USING MESSAGE = 'The target is not affiliated with this parent';
END IF;
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER %(trigger)s BEFORE INSERT OR UPDATE
ON %(table)s
FOR EACH ROW EXECUTE PROCEDURE %(function)s();
''',
context={
'table': primary_table_name,
'function': '%s_validate' % primary_table_name,
'trigger': '%s_trigger' % primary_table_name,
'parentcol': parentcol,
'child_table_name': child_table_name,
'child_id_column': child_id_columns[0],
'lhs': '%s_%s' % (parent_table_name, parent_id_columns[0]),
'rhs': '%s_%s' % (child_table_name, child_id_columns[0]),
}
).execute_if(dialect='postgresql')
)
event.listen(primary_table, 'before_drop',
DDL('''
DROP TRIGGER %(trigger)s ON %(table)s;
DROP FUNCTION %(function)s();
''',
context={
'table': primary_table_name,
'trigger': '%s_trigger' % primary_table_name,
'function': '%s_validate' % primary_table_name,
}
).execute_if(dialect='postgresql')
)