Просьба к пользователям PDO/Mysql

Фанат

oncle terrible
Команда форума
выполнить приведённый ниже код и написать в тему то, что он выведет
PHP:
$dbh->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
try {
  $sth = $dbh->prepare("VYBRAT * IZ users GDE 1 = ?");
  $sth->execute(array("1"));
} catch (PDOException $e) {
  echo $e->getMessage();
}
$dbh здесь, соответственно - объект PDO.
 

shureen

Милорд Лось Кристофер
SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'VYBRAT * IZ users GDE 1 = '1''
 

Mols

Новичок
SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'VYBRAT * IZ users GDE 1 = '1'' at line 1
 

Mols

Новичок
PHP:
$dbh->exec('SET NAMES utf8');
Тока помидорами не бросать)))
З.Ы.
К конфе подготовка?
 

Фанат

oncle terrible
Команда форума
ага, к ней :)
помидорами ни в кого кидаться не буду, и другим не дам.
собственно, там вариантов-то других нет: только тем или иным способом выполнить этот запрос

да и не для того я спрашиваю. мне просто нужна статистика использования PDO.
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
я постоянно использую pdo
как вы выставляете кодировку, просьба привести строчку из кода, скопировав её как есть.
PHP:
        'db'=>array(
            'connectionString' => 'mysql:host=localhost;dbname=kiseki',
            'emulatePrepare' => false,
            'username' => 'root',
            'password' => '',
            'charset' => 'utf8',
        ),
:D
 

zerkms

TDD infected
Команда форума
grigori
Ответа на вопрос собственно ты и не дал. Никакой гарантии, что ['db']['charset'] в принципе юзается нет. (по крайней мере по приведённому куску кода это совершенно неочевидно)
 

fixxxer

К.О.
Партнер клуба
Спасибо!

И, вдогонку, ещё один вопрос - как вы выставляете кодировку, просьба привести строчку из кода, скопировав её как есть.
PHP:
    protected function assemblePdoConnection() {
        $dsn        = $this->dsn;
        $kwargs     = $this->connection_args;
        $login      = !empty($kwargs['login'])    ? $kwargs['login']    : null;
        $password   = !empty($kwargs['password']) ? $kwargs['password'] : null;
        $options    = array();
        if (!empty($kwargs['charset'])) {
            $options[\ PDO::MYSQL_ATTR_INIT_COMMAND] = sprintf("SET NAMES '%s'", $kwargs['charset']);
        }
        return new \ PDO($dsn, $login, $password, $options);
    }
Еще вроде бы в каких-то самых последних версиях добавляли поддержку charset= в DSN для PDO_Mysql. У меня на php 5.3.5 не работает.
Кстати, проверьте у кого 5.3.6 (или даже найтли билды) под рукой, как то так
Код:
fixxxer@localhost ~$ php -r '
$pdo=new PDO("mysql:host=localhost;charset=utf8","root");
$st=$pdo->prepare("select @@character_set_client");
$st->execute();
var_dump($st->fetch());
'
array(2) {
  ["@@character_set_client"]=>
  string(6) "latin1"
  [0]=>
  string(6) "latin1"
}
 

Фанат

oncle terrible
Команда форума
если оно так и пишет latin1, то пользы в оном нововведении немного :)
 

Фанат

oncle terrible
Команда форума
Еще вроде бы в каких-то самых последних версиях добавляли поддержку charset= в DSN для PDO_Mysql. У меня на php 5.3.5 не работает.
Кстати, проверьте у кого 5.3.6 (или даже найтли билды) под рукой, как то так
Блин, ты меня пугаешь. Полез в исходники смотреть, не добавили ли туда mysql_set_character_set().
Вроде, нет...
 

fixxxer

К.О.
Партнер клуба
Ну у меня-то как раз не работает. Потому и latin1. :)

Я вообще может и гоню, у меня в голове почему-то отложилось, что в каком-то changelog-е видел. Щас вот найти не могу, может меня глючит.
 

Фанат

oncle terrible
Команда форума
не, само по себе указание чарсета в ДСНе как раз есть: http://php.net/ChangeLog-5.php
но меня интересует, как оно сделано внутри - кошерно, через mysql_set_character_set(), или посылкой запроса.
И чё-то я в исходниках никак разобраться не могу...
 

fixxxer

К.О.
Партнер клуба
#ifdef PDO_MYSQL_HAS_CHARSET
if (vars[0].optval && mysql_options(H->server, MYSQL_SET_CHARSET_NAME, vars[0].optval)) {
pdo_mysql_error(dbh);
goto cleanup;
}
#endif

mysqlnd_libmysql_compat.h:#define mysql_options(r,a,b) mysqlnd_options((r), (a), (b))

mysqlnd.h:#define mysqlnd_options(conn, opt, value) (conn)->m->set_client_option((conn), (opt), (value) TSRMLS_CC)

mysqlnd.c:MYSQLND_METHOD(mysqlnd_conn, set_client_option)
...
case MYSQL_SET_CHARSET_NAME:
...
conn->options.charset_name = new_charset_name;

mysqlnd.c: /* {{{ mysqlnd_connect_run_authentication */
static enum_func_status
mysqlnd_connect_run_authentication(
....
if (options->charset_name && (charset = mysqlnd_find_charset_name(options->charset_name))) {
auth_packet->charset_no = charset->nr;
} else {
#if MYSQLND_UNICODE
auth_packet->charset_no = 200;/* utf8 - swedish collation, check mysqlnd_charset.c */
#else
auth_packet->charset_no = greet_packet->charset_no;
#endif
}

таки задается кодировка соединения, передаваемая при аутентификации (видимо первым же пакетом при установке соединения). Это если с mysqlnd собрано (обычно с ним собирают), libmysqlclient смотреть лениво ;)

а mysql_set_charactet_set там нафиг не надо, ибо prepared statements
 

Фанат

oncle terrible
Команда форума
Во, круто! ext/pdo_mysql/mysql_driver.c я накопал, а дальше не пролез.
Понятненько!
а mysql_set_charactet_set там нафиг не надо, ибо prepared statements
Вооооот об этом и будет мой доклад %)
Prepared statements в PDO по умолчанию выключены ;-)
 

fixxxer

К.О.
Партнер клуба
Ну, скажем так, не выключены, а эмулируются.
Но я не вижу разницы, если не связываться с многобайтными кодировками отличными от utf8.

А вообще, сами по себе perpared statements очень ограничивают в возможностях составления запроса. Даже банально array подставить в in нельзя.

Ну и типизацию мне кажется правильнее задавать в шаблоне запроса.

Потому я его использую только для всякой мелочи, где нельзя или нежелательно свои extension-ы ставить на сервер.
 

Фанат

oncle terrible
Команда форума
Ну, эмулировать там сложно. Поэтому я бы скорее сказал - заменяются тупым искейпингом. Особенно забавно наблюдать запрос с нетипизованными плейсхолдерами в LIMIT.
Разницы, действительно, немного, но осадочек остаётся :)
 

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
Я передаю нечто вроде:

PHP:
$config['connection'] = array(
    'host'           => '127.0.0.1',
    'username'       => 'db',
    'password'       => 'pass',
    'dbname'         => 'dbname',
    'filename'       => '',
    'options'        => array('DSN_LINK_NAME' => 'MySQL', PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES UTF8")
);
Эти данные передаются фабрике, которая и возвращает объект.
 

fixxxer

К.О.
Партнер клуба
Ну, эмулировать там сложно. Поэтому я бы скорее сказал - заменяются тупым искейпингом. Особенно забавно наблюдать запрос с нетипизованными плейсхолдерами в LIMIT.
Разницы, действительно, немного, но осадочек остаётся :)
Ну, у меня вокруг этого дела враппер, который делает так
PHP:
    public function bind($parameters) {
        foreach ($parameters as $key => $value) {
            $this->PdoStatement->bindValue(
                (is_integer($key) || ctype_digit($key)) ? $key : ":$key",
                $value,
                $this->getPdoType($value)
            );
        }
        return $this;
    }

    protected function getPdoType($value) {
        $php_type = gettype($value);
        return array_key_exists($php_type, self::$php_to_pdo_types_map)
            ? self::$php_to_pdo_types_map[$php_type]
            : self::$php_to_pdo_types_map['default'];
    }

    static protected $php_to_pdo_types_map = array(
        'boolean'   => \ PDO::PARAM_BOOL,
        'NULL'      => \ PDO::PARAM_NULL,
        'integer'   => \ PDO::PARAM_INT,
        'default'   => \ PDO::PARAM_STR,
    );
и предполагается, что я не идиот и делаю (int) итд где надо.

Правда, от отрицательного числа в limit, и подобной фигни, это не спасает :) Ну тут уж руками
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
zerkms это шутка, дальше yii делает $pdo->exec('SET NAMES '.$pdo->quote($this->charset));, и других вариантов до 5.3.6 не было

проверьте у кого 5.3.6 (или даже найтли билды) под рукой, как то так
на 5.3.6 работает
[root@devel ~]# php -r '
$pdo=new PDO("mysql:host=localhost;charset=koi8r","root");
$st=$pdo->prepare("select @@character_set_client");
$st->execute();
var_dump($st->fetch());
'
array(2) {
["@@character_set_client"]=>
string(5) "koi8r"
[0]=>
string(5) "koi8r"
}
[root@devel ~]# php -r '
$pdo=new PDO("mysql:host=localhost;charset=utf8","root");
$st=$pdo->prepare("select @@character_set_client");
$st->execute();
var_dump($st->fetch());
'
array(2) {
["@@character_set_client"]=>
string(4) "utf8"
[0]=>
string(4) "utf8"
}
а в мануале по PDO_MYSQL DSN все еще "charset Currently ignored."
 
Сверху