PostgreSQL и fixtures

Предварительное обсуждение найденных ошибок перед отправкой их авторам фреймворка, а также внесение новых предложений.
Ответить
uni_advisor
Сообщения: 8
Зарегистрирован: 2012.07.19, 15:52

PostgreSQL и fixtures

Сообщение uni_advisor »

Начал изучать Yii. Использую PostgreSQL. При unit-тестировании моделей при заполнении их фикстурами столкнулся с ошибкой: permission denied: "RI_ConstraintTrigger_16572".
В логах PostgreSQL: ALTER TABLE "tbl_user" DISABLE TRIGGER ALL permission denied: "RI_ConstraintTrigger_16572".
Получается, что Fixture Manager перед заполнением данных отключает ограничения, триггеры. Какие могут быть решения ?
  1. Дать права superuser пользователю.
    Крайне глупое решение согласны ? В приложениях, как правило, используется пользователь с ограниченными правами для работы с базой данных и тестирование операций с БД необходимо проводить именно этими ограниченными пользователями.
  2. Использовать несколько соединений с базой данных.
    На этапе подготовки БД соединяться как superuser (отключение ограничений, очистка таблиц, подготовка и заливка данных). А уже при запуске тестов - осуществлять соединение обычным пользователем (или делать переключение ролей).
На эту тему нашел пост на http://www.yiiframework.com/forum/index ... nttrigger/
Они используют в PostgreSQL особенность, что в рамках транзакции можно отключить проверку ограничений для каждой операции непосредственно, а осуществлять проверки уже только при подтверждении транзакции. Но это уже трюки, кроме того, этот фокус может не пройти с другими базами!
Я пока что вижу такое решение. В конфиге прописываем параметр для соединения с базой данных как суперюзер, наследуем класс для работы с фикстурами и переписываем методы, которые осуществляют очистку и загрузку базы, чтобы использовали другой коннект (суперюзера).
Ваши мысли на эту тему ?
uni_advisor
Сообщения: 8
Зарегистрирован: 2012.07.19, 15:52

Re: PostgreSQL и fixtures

Сообщение uni_advisor »

В FixtureManager жестко прошито использовать соединение 'db'.
В соединении db мы можем указать соединяться как superuser, а ниже создать еще одно соединение 'db_user'

Код: Выделить всё

        'db_user'=>array(
                'connectionString' => 'pgsql:host=localhost;port=5432;dbname=trackstar_test',
                'username' => 'trackstar',
                'password' => 'trackstar',
                'charset' => 'utf8',
                'class'   => 'CDbConnection',
        ),

и в юнит-тестах использовать при тестировании методов использовать именно это соединение, тогда как загрузка фикстур будет происходить от суперпользователя.
Или можно наследовать класс CDbFixtureManager и переопределить в нем метод getDbConnection, чтобы использовал соединение от суперюзера.
Пока что обошелся методом, как советовали на форуме. В каталоге tests создал CUnitTestPgsqlSchema.php и переопределил метод checkIntegrity

Код: Выделить всё

class CUnitTestPgsqlSchema extends CPgsqlSchema 
{
    protected function setUp()
    {
        parent::setUp();
    }

    public function checkIntegrity($check=true,$schema='')
    {
        $tableNames=$this->getTableNames($schema);
        $db=$this->getDbConnection();
        
        if ($check) {
            $db->createCommand("SET CONSTRAINTS ALL DEFERRED")->execute();
        } else {
            $db->createCommand("SET CONSTRAINTS ALL IMMEDIATE")->execute();
        }
    }
    
}
 
В любом случае в классе CPgsqlSchema строчка

Код: Выделить всё

$db->createCommand("ALTER TABLE $tableName $enable TRIGGER ALL")->execute();
 
Мне кажется слишком радикальной, так как требует прав суперпользователя.
Ответить