日記帳
本ページはプロモーションが含まれています
カテゴリー
Links
blog(ブログ)マスター
アンドロイドの巣
ゼロから始めるベランダ菜園
タイトル
2024年11月
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30

PDO::mysql_client_encodingの実装についての研究

2011-02-14
PDO::mysql_client_encodingが 無くてSQLで発行すると不便なので実装してみた。

PDO::mysql_set_charset($charsetname)
PDO::mysql_client_encoding()
PDO::mysql_select_db($dbname)

使い方
  $dbh->mysql_set_charset('utf8');
  echo $dbh->mysql_client_encoding();

同じことをsqlで発行するには
  $dbh->exec('SET CHARACTER SET utf8 ');
  show variables like 'character_set_client' で Value列を取得

SQLレベルでPDOに実装をまねるなら PDOクラスを継承するといい。
もし、外部から値を受け取る場合は、
その際は、外部から値を受け付けないようにSQLインジェクション対策が必要だろう。
SHOW CHARACTER SETを使うと一覧がとれるので、その中と照合して、設定するようにすれば、よい。

今回は、PDO_MysqlのCソースレベルで対応した。
PHP_ME , PHP_METHOD の PHP_をZEND_にするようにとヘルプにはあったが、
・名前が嫌い、銘銘方法がきにくわない(企業名だし)
・他のPDOが使っていない
ということで今回は使うのは避けた。

有効桁の低い+中途半端なスクリプト言語に期待しても意味がないし、
わざわざ、PDO Cソースレベルので改造は、
コンパイルなどの手間がかかるので
素直に、適当な関数を作るか、PDOを継承したクラスにスクリプトコードで実装するほうが現実的だろう。


「実行結果」
sql: mysql_client_encoding: latin1
 get_class :PDO
 is_a($dbh ,'PDO') :true
 is_a($dbh ,'PDO_MYSQL') :false
 $dbh instanceof PDO_MYSQL :false
 PDO::ATTR_DRIVER_NAME  :mysql
 PDO::ATTR_SERVER_VERSION  :5.1.31-community
 PDO::ATTR_CLIENT_VERSION  :5.0.67

check encoding
 mysql_client_encoding: latin1
 set utf8 :true
 mysql_client_encoding: utf8

mysql_select_db true



[スクリプトソース]
<?php
//  ../../php-test/bin/php -d extension_dir=$PWD/modules/ ../../pdo_mysql_charset_check.php
//  php-test/bin/php -d extension_dir=ext/pdo_mysql/modules/ pdo_mysql_charset_check.php

 $ext_mysql_name = "pdo_mysql";
  if (!extension_loaded ($ext_mysql_name))
    dl($ext_mysql_name.((preg_match('/win/i',PHP_OS))?".dll":".so"));

  if (preg_match('/win/i',PHP_OS))
     $host = "localhost";
    else
     $host = "192.168.1.1"; //

try {
  $dbh = new PDO("mysql:host=$host;dbname=test;","test","");
} catch (PDOException $e) {
}

 if (!method_exists($dbh, "mysql_set_charset"))
 {
   exit("no function: PDO::mysql_set_charset\n");
 }
 
  echo "\n";
//  show variables like 'character_set_client'
//  show variables like 'character_set_server'
//  result:  Variable_name ,  Value
 if ( $sth = $dbh->prepare("show variables like 'character_set_client'") )
  if ($sth->execute())
       echo "sql: mysql_client_encoding: ".$sth->fetchColumn(1)."\n";
//  sleep(10); // discnnnect test: waite 10 sec
 
  echo " get_class :". get_class($dbh)."\n";
  echo " is_a(\$dbh ,'PDO') :". (is_a($dbh, "PDO") ? "true" : "false") ."\n";
  echo " is_a(\$dbh ,'PDO_MYSQL') :". (is_a($dbh, "PDO_MYSQL") ? "true" : "false") ."\n";
  echo " \$dbh instanceof PDO_MYSQL :". (($dbh instanceof PDO_MYSQL) ? "true" : "false") ."\n";
  echo " PDO::ATTR_DRIVER_NAME  :". $dbh->getAttribute(PDO::ATTR_DRIVER_NAME) ."\n";
  echo " PDO::ATTR_SERVER_VERSION  :". $dbh->getAttribute(PDO::ATTR_SERVER_VERSION) ."\n";
  echo " PDO::ATTR_CLIENT_VERSION  :". $dbh->getAttribute(PDO::ATTR_CLIENT_VERSION) ."\n";
  echo "\n";
 
  echo "check encoding "."\n";
  echo " mysql_client_encoding: ".$dbh->mysql_client_encoding()."\n";
  echo " set utf8 :". ($dbh->mysql_set_charset("utf8") ? "true" : "false") ."\n";
  echo " mysql_client_encoding: ".$dbh->mysql_client_encoding()."\n";
//  echo "mysql_client_encoding: ".PDO::mysql_client_encoding()."\n";
  echo "\n";

  echo "mysql_select_db ". ($dbh->mysql_select_db("test") ? "true" : "false") ."\n";

?>


[php pdoドライバソース差分] copyright okamerin.com
--- php-5.2.17/ext/pdo_mysql/mysql_driver.c    2010-01-12 21:46:54.000000000 +0900
+++ php-5.2.17/ext/pdo_mysql/mysql_driver.c    2011-02-10 00:00:00.000000000 +0900
@@ -33,6 +33,9 @@
 #include <mysqld_error.h>
 #include "zend_exceptions.h"
 
+#if (MYSQL_VERSION_ID >= 40113 && MYSQL_VERSION_ID < 50000) || MYSQL_VERSION_ID >= 50007
+#define MYSQL_HAS_SET_CHARSET
+#endif
 
 const char *pdo_mysql_get_sqlstate(unsigned int my_errno) {
     switch (my_errno) {
@@ -408,6 +411,93 @@
 }
 /* }}} */
 
+#ifdef MYSQL_HAS_SET_CHARSET
+static PHP_METHOD(PDO, mysql_set_charset)
+{
+    pdo_dbh_t *dbh;
+    pdo_mysql_db_handle *H;
+    char *csname;
+    int csname_len;
+
+    dbh = zend_object_store_get_object(getThis() TSRMLS_CC);
+    PDO_CONSTRUCT_CHECK;
+
+    H = (pdo_mysql_db_handle *)dbh->driver_data;
+    if (!H->server) { RETURN_FALSE; }
+
+    if (ZEND_NUM_ARGS() <= 0) { WRONG_PARAM_COUNT; }
+
+    if (zend_parse_parameters(1 TSRMLS_CC, "s", &csname, &csname_len) == FAILURE) { RETURN_FALSE; }
+
+    // Zero for success.
+    if (0 == mysql_set_character_set(H->server, csname) )
+       { RETURN_TRUE; }
+      else
+       { RETURN_FALSE; }
+}
+#endif
+
+static PHP_METHOD(PDO, mysql_client_encoding)
+{
+    pdo_dbh_t *dbh;
+    pdo_mysql_db_handle *H;
+
+    dbh = zend_object_store_get_object(getThis() TSRMLS_CC);
+    PDO_CONSTRUCT_CHECK;
+
+    H = (pdo_mysql_db_handle *)dbh->driver_data;
+    if (!H->server) { RETURN_EMPTY_STRING(); }
+
+    if (ZEND_NUM_ARGS() > 0) { WRONG_PARAM_COUNT; }
+
+   RETURN_STRING((char *)mysql_character_set_name(H->server) , 1);
+}
+
+static PHP_METHOD(PDO, mysql_select_db)
+{
+    pdo_dbh_t *dbh;
+    pdo_mysql_db_handle *H;
+    char *dbname;
+    int dbname_len;
+
+    dbh = zend_object_store_get_object(getThis() TSRMLS_CC);
+    PDO_CONSTRUCT_CHECK;
+
+    H = (pdo_mysql_db_handle *)dbh->driver_data;
+    if (!H->server) { RETURN_FALSE; }
+
+    if (ZEND_NUM_ARGS() != 1) { WRONG_PARAM_COUNT; }
+
+    if (zend_parse_parameters(1 TSRMLS_CC, "s", &dbname, &dbname_len) == FAILURE) { RETURN_FALSE; }
+
+    // Zero for success.
+    if (0 == mysql_select_db(H->server, dbname) )
+       { RETURN_TRUE; }
+      else
+       { RETURN_FALSE; }
+}
+
+static zend_function_entry dbh_methods[] = {
+#ifdef MYSQL_HAS_SET_CHARSET
+    PHP_ME(PDO, mysql_set_charset,     NULL, ZEND_ACC_PUBLIC)
+#endif
+    PHP_ME(PDO, mysql_client_encoding, NULL, ZEND_ACC_PUBLIC)
+    PHP_ME(PDO, mysql_select_db,       NULL, ZEND_ACC_PUBLIC)
+    {NULL, NULL, NULL}
+};
+// mysql_get_client_version() , PDO::getAttribute(PDO::ATTR_CLIENT_VERSION)
+// mysql_get_server_version() , PDO::getAttribute(PDO::ATTR_SERVER_VERSION)
+
+static zend_function_entry *pdo_mysql_get_driver_methods(pdo_dbh_t *dbh, int kind TSRMLS_DC)
+{
+    switch (kind) {
+        case PDO_DBH_DRIVER_METHOD_KIND_DBH:
+            return dbh_methods;
+        default:
+            return NULL;
+    }
+}
+
 static struct pdo_dbh_methods mysql_methods = {
     mysql_handle_closer,
     mysql_handle_preparer,
@@ -420,7 +510,8 @@
     pdo_mysql_last_insert_id,
     pdo_mysql_fetch_error_func,
     pdo_mysql_get_attribute,
-    pdo_mysql_check_liveness
+    pdo_mysql_check_liveness,
+    pdo_mysql_get_driver_methods  /* get_driver_methods */
 };
 
 #ifndef PDO_MYSQL_UNIX_ADDR



PR

[PR]