Исправление ошибки в INSERT INTO … SELECT в Kohana 3 при использовании конфигурации базы данных, отличной от default

Исправление короче описания

Ситуация: нужно выполнить запрос вида

[-]
View Code SQL
INSERT INTO `table` (`col1`, `col2`) SELECT * FROM `table` WHERE `col1` <> 0;

Если использовать конфигурацию default, то всё отлично работает. Если же использовать другую конфигурацию, то можем получить ошибку соединения с базой данных и исключение.

Например:

[-]
View Code PHP
<?php
// application/config/database.php
// Важно, чтобы в конфигурации default нельзя было подключиться к серверу
return array(
    'test' => array(
        'type'       => 'mysql',
        'connection' => array(
            'hostname'   => 'localhost',
            'database'   => 'test',
            'username'   => 'username',
            'password'   => 'password',
            'persistent' => FALSE,
        ),
        'table_prefix' => '',
        'charset'      => 'utf8',
        'caching'      => FALSE,
        'profiling'    => TRUE,
    ),
);
?>

<?php
// application/classes/controller/welcome.php

class Controller_Welcome extends Controller
{
    public function action_index()
    {
        $this->request->response = DB::insert('test', array('col1', 'col2'))
                                    ->select(DB::select()->from('test')->where('column1', '<>', '0'))
                                    ->compile(Database::instance('test')) . "\n";
    }
}

?>

Важно, чтобы правая часть условия в where() была строкой.

В результате если мы запустим проект, то получим что-то вида:

[-]
View Code Text
INSERT INTO `test` (`column1`, `column2`) ErrorException [ 2 ]: mysql_connect(): Access denied for user 'www-data'@'localhost' (using password: NO) ~ MODPATH/database/classes/kohana/database/mysql.php [ 56 ]

Связано это с особенностью реализации метода _Database_Query_Builder_Insert::compile():

[-]
View Code PHP
    public function compile(Database $db)
    {
        // Start an insertion query
        $query = 'INSERT INTO '.$db->quote_table($this->_table);

        // Не интересно
        // …

        if (is_array($this->_values))
        {
            // Не интересно
            // …
            $query .= 'VALUES '.implode(', ', $groups);
        }
        else
        {
            // Add the sub-query
            $query .= (string) $this->_values;
        }

        return $query;
    }

Строка $query .= (string) $this->_values; вызывает метод compile() для SELECT, но так как конфигурация базы данных не передаётся, используется конфигурация default.

Самое простое исправление очевидно: заменить строку

[-]
View Code PHP
$query .= (string) $this->_values;

на

[-]
View Code PHP
$query .= $this->_values->compile($db);

Тем не менее, если SELECT использует одну базу данных, а INSERT — другую, и при этом используются разные charset’ы (да, это не самое большое извращение — бывают и хуже), этого будет недостаточно. В этом случае нужно добавить дополнительный параметр в метод select(), указывающий, какую конфигурацию использовать. Требуемые изменения кода тривиальны, посему остаются упражнением интересующемуся читателю.

Автор: ; опубликовано в: Kohana; метки: Kohana, Kohana 3, MySQL, база данных, ошибка
12
Авг
2010

RSS Комментарии к статье «Исправление ошибки в INSERT INTO … SELECT в Kohana 3 при использовании конфигурации базы данных, отличной от default»  »

К статье «Исправление ошибки в INSERT INTO … SELECT в Kohana 3 при использовании конфигурации базы данных, отличной от default» комментариев пока нет. Не хотите ли стать первым?

Пожалуйста, не используйте эту форму для комментирования! Данная форма предназначена исключительно для ботов.

Оставить комментарий к записи «Исправление ошибки в INSERT INTO … SELECT в Kohana 3 при использовании конфигурации базы данных, отличной от default»

Ваш e-mail не будет опубликован. Обязательные поля помечены *

*

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Оставляя комментарий, вы выражаете своё согласие с Правилами комментирования.

Подписаться, не комментируя

गते गते पारगते पारसंगते बोधि स्वाहा