Changeset 20492

Show
Ignore:
Timestamp:
10/02/08 18:12:10 (3 months ago)
Author:
nowelium
Message:

mysql の procedure サポートは終わり。
General error: 2014 Cannot execute queries while other unbuffered queries are active. とかは、PDOのPDO::MYSQL_ATTR_USE_BUFFERED_QUERY をいくら設定してもダメなので、少し逃げ。一端切断すればなんとかなるけど、Datasource設定とかは管理外なので、やらない。
multi rows は 2次元配列で。

Location:
lang/php/misc/Hermit
Files:
6 added
18 modified

Legend:

Unmodified
Added
Removed
  • lang/php/misc/Hermit/src/Hermit/HermitParam.php

    r20387 r20492  
    55 */ 
    66class HermitParam extends stdClass { 
     7    public function set($name, $value){ 
     8        $this->$name = $value; 
     9    } 
     10    public function get($name){ 
     11        return $this->$name; 
     12    } 
    713    public function getPropertyNames(){ 
    814        $names = array(); 
     
    1218        return $names; 
    1319    } 
     20    public function __toString(){ 
     21        $tos = array(); 
     22        foreach($this as $name => $value){ 
     23            $tos[] = $name . '=>' . $value; 
     24        } 
     25        return __CLASS__ . ' {' . join(',', $tos) . '}'; 
     26    } 
    1427} 
  • lang/php/misc/Hermit/src/Hermit/annote/HermitAnnoteConst.php

    r20387 r20492  
    1111    const FILE_SUFFIX = '_FILE'; 
    1212    const PROCEDURE_SUFFIX = '_PROCEDURE'; 
    13     const DELEGATE_SUFFIX = '_DELEGATE'; 
    1413    const VALUE_TYPE_SUFFIX = '_VALUE_TYPE'; 
    1514 
  • lang/php/misc/Hermit/src/Hermit/command/HermitProcedureCommand.php

    r20417 r20492  
    2121        $this->annote = $annote; 
    2222    } 
    23  
    2423    public function execute(PDO $pdo, array $parameters){ 
     24        if($this->sqlCreator instanceof HermiSetupSqlCreator){ 
     25            if($this->sqlCreator->hasSetupSql()){ 
     26                $setupBuilder = new HermitSetupStatementBuilder($this->method, $this->annote, $this->sqlCreator); 
     27                $setupStatement = $setupBuilder->build($pdo); 
     28                $setupStatement->execute($parameters); 
     29            } 
     30        } 
     31         
    2532        $builder = new HermitProcedureStatementBuilder($this->method, $this->annote, $this->sqlCreator); 
    2633        $stmt = $builder->build($pdo); 
    2734        $stmt->execute($parameters); 
    2835        $rs = HermitProcedureResultSetFactory::create($pdo, $stmt->getSqlParameter()); 
     36// 
     37//        to pdo_mysql cause: Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other unbuffered queries are active. 
     38//        if($rs instanceof HermitParameterBind){ 
     39//            $rs->bindParameter($pdo, $parameters); 
     40//        } 
     41//        return $rs->execute($stmt, $this->type); 
     42// 
     43        $returnValue = $rs->execute($stmt, $this->type); 
    2944        if($rs instanceof HermitParameterBind){ 
    3045            $rs->bindParameter($pdo, $parameters); 
    3146        } 
    32         return $rs->execute($stmt, $this->type); 
     47        return $returnValue; 
    3348    } 
    3449} 
  • lang/php/misc/Hermit/src/Hermit/creator/HermitProcedureCallSqlCreator.php

    r20387 r20492  
    44 * @author nowelum 
    55 */ 
    6 class HermitProcedureCallSqlCreator implements HermitSqlCreator { 
     6class HermitProcedureCallSqlCreator implements HermitSqlCreator, HermiSetupSqlCreator { 
    77    private $sql; 
     8    private $setupSql; 
    89    public function initialize(PDO $pdo, ReflectionMethod $method, HermitAnnote $annote){ 
    910        $procedureName = $annote->getProcedure($method); 
    1011        $dbMeta = HermitDatabaseMetaFactory::get($pdo); 
    1112        $info = $dbMeta->getProcedureInfo($procedureName); 
    12         $parameterNames = $info->getParamNames(); 
    13         $sql = 'CALL'; 
    14         $sql .= ' '; 
    15         $sql .= $procedureName; 
    16         $sql .= '('; 
    17         foreach($parameterNames as $parameterName){ 
    18             $sql .= '/*' . $parameterName . '*/'; 
    19             $sql .= '"' . $parameterName . '"'; 
    20             $sql .= ','; 
    21         } 
    22         $sql = substr($sql, 0, -1); 
    23         $sql .= ')'; 
    24         $this->sql = $sql; 
     13 
     14        $this->setupSql = self::generateSetupSql($info); 
     15        $this->sql = self::generateCallSql($info); 
    2516    } 
    2617    public function createSql(){ 
    2718        return $this->sql; 
    2819    } 
     20    public function createSetupSql(){ 
     21        return $this->setupSql; 
     22    } 
     23    public function hasSetupSql(){ 
     24        return null !== $this->setupSql; 
     25    } 
     26    protected static function generateCallSql(HermitProcedureInfo $info){ 
     27        $parameterNames = $info->getParamNames(); 
     28        $callSql = 'CALL'; 
     29        $callSql .= ' '; 
     30        $callSql .= $info->getName(); 
     31        $callSql .= '('; 
     32        foreach($parameterNames as $parameterName){ 
     33            $callSql .= '/*' . $parameterName . '*/'; 
     34            $callSql .= '"' . $parameterName . '"'; 
     35            $callSql .= ','; 
     36        } 
     37        $callSql = substr($callSql, 0, -1); 
     38        $callSql .= ')'; 
     39        return $callSql; 
     40    } 
     41    protected static function generateSetupSql(HermitProcedureInfo $info){ 
     42        $begin = false; 
     43        $parameterNames = $info->getParamNames(); 
     44 
     45        $setupSql = 'SET'; 
     46        $setupSql .= ' '; 
     47        foreach($parameterNames as $parameterName){ 
     48            if($info->typeofIn($parameterName)){ 
     49               continue; 
     50            } 
     51            $begin = true; 
     52            $setupSql .= '@' . $parameterName; 
     53            $setupSql .= ' = '; 
     54            $setupSql .= '/*' . $parameterName . '*/'; 
     55            $setupSql .= '"' . $parameterName . '"'; 
     56            $setupSql .= ','; 
     57        } 
     58        if(!$begin){ 
     59            return null; 
     60        } 
     61        return substr($setupSql, 0, -1); 
     62    } 
    2963} 
  • lang/php/misc/Hermit/src/Hermit/meta/HermitMySQLDatabaseMeta.php

    r20314 r20492  
    55 */ 
    66class HermitMySQLDatabaseMeta implements HermitDatabaseMeta { 
     7     
    78    const USING_DB_NAME_SQL = 'SELECT database()'; 
    89    const TABLE_INFO_SQL = 'SELECT * FROM %s LIMIT 0'; 
    910    const PROCEDIRE_INFO_SQL = 'SELECT param_list, returns FROM mysql.proc WHERE db = :db AND name = :name'; 
     11     
    1012    private $tables = array(); 
    1113    private $procedures = array(); 
     
    3739            } 
    3840        } 
     41        $stmt->closeCursor(); 
     42        unset($stmt); 
    3943        return $this->tables[$table] = $info; 
    4044    } 
     
    4650        $stmt->execute(array(':db' => $this->databaseName, ':name' => $procedure)); 
    4751        $paramList = $stmt->fetchColumn(0); 
     52        if(false === $paramList){ 
     53            throw new InvalidArgumentException('not found procedure name: ' . $procedure . ' in db: ' . $this->databaseName); 
     54        } 
    4855 
    4956        $info = new HermitProcedureInfo; 
     57        $info->setName($procedure); 
    5058        $chunk = array_map('trim', explode(',', $paramList)); 
    5159        foreach($chunk as $field){ 
     
    7886        } 
    7987 
     88        $stmt->closeCursor(); 
     89        unset($stmt); 
    8090        return $this->procedures[$procedure] = $info; 
    8191    } 
     
    8494        $stmt = $this->pdo->prepare(self::USING_DB_NAME_SQL); 
    8595        $stmt->execute(); 
    86         return $stmt->fetchColumn(0); 
     96        $result = $stmt->fetchColumn(0); 
     97         
     98        $stmt->closeCursor(); 
     99        unset($stmt); 
     100        return $result; 
    87101    } 
    88102} 
  • lang/php/misc/Hermit/src/Hermit/meta/HermitProcedureInfo.php

    r20325 r20492  
    55 */ 
    66class HermitProcedureInfo implements Serializable { 
     7     
    78    const IN_TYPE = 1; 
    89    const OUT_TYPE = 2; 
    910    const INOUT_TYPE = 3; 
    1011 
     12    private $procedureName; 
    1113    private $names = array(); 
    1214    private $inout = array(); 
     
    2931        } 
    3032    } 
    31  
     33     
     34    public function setName($name){ 
     35        $this->procedureName = $name; 
     36    } 
     37    public function getName(){ 
     38        return $this->procedureName; 
     39    } 
    3240    public function addParamName($name){ 
    3341        $this->names[] = $name; 
  • lang/php/misc/Hermit/src/Hermit/parameter/HermitMySqlProcedureParameter.php

    r20417 r20492  
    3131        $param = $value[0]; 
    3232        foreach($this->bindKeys as $index => $key){ 
    33             $prefix = ''; 
    3433            if($this->info->typeofIn($key)){ 
    3534                $stmt->bindParam(':' . $key, $param->$key); 
  • lang/php/misc/Hermit/src/Hermit/parameter/HermitProcedureParameter.php

    r20417 r20492  
    3030    public function bind(PDOStatement $stmt, $value){ 
    3131        $param = $value[0]; 
     32        $propertyNames = $param->getPropertyNames(); 
     33 
    3234        foreach($this->bindKeys as $index => $key){ 
    3335            $bindKey = ':' . $key; 
    3436            if($this->info->typeofIn($key)){ 
     37                if(!in_array($key, $propertyNames)){ 
     38                    throw new InvalidArgumentException('param ' . $param . ' has not propery: ' . $key . ' instatement: ' . $stmt->queryString); 
     39                } 
    3540                $stmt->bindParam($bindKey, $param->$key); 
    3641                continue; 
    3742            } 
    38             $paramValue = $param->$key; 
     43             
     44            $paramValue = null; 
     45            if(isset($param->$key)){ 
     46                $paramValue =  $param->$key; 
     47            } 
    3948            if(null === $paramValue){ 
    40                 $stmt->bindParam($bindKey, null, PDO::PARAM_NULL | PDO::PARAM_INPUT_OUTPUT); 
     49                $stmt->bindParam($bindKey, $paramValue, PDO::PARAM_NULL | PDO::PARAM_INPUT_OUTPUT); 
    4150                continue; 
    4251            } 
  • lang/php/misc/Hermit/src/Hermit/resultset/HermitDefaultResultSet.php

    r20417 r20492  
    77    public function execute(HermitStatement $stmt, HermitValueType $type){ 
    88        $type->apply($stmt); 
    9         return $stmt->fetch(); 
     9        if($row = $stmt->fetch()){ 
     10            $stmt->closeCursor(); 
     11            return $row; 
     12        } 
     13        return null; 
    1014    } 
    1115} 
  • lang/php/misc/Hermit/src/Hermit/resultset/HermitMySqlProcedureResultSet.php

    r20417 r20492  
    44 * @author nowelium 
    55 */ 
    6 class HermitMySqlProcedureResultSet extends HermitProcedureResultSet { 
     6class HermitMySqlProcedureResultSet extends HermitProcedureResultSet implements HermitParameterBind { 
    77    /** 
    88     * @override 
     
    1818            $stmt->bindColumn(1, $param->$name); 
    1919            $stmt->execute(); 
    20              
     20 
    2121            $stmt->fetch(PDO::FETCH_BOUND); 
    2222            $stmt->closeCursor(); 
  • lang/php/misc/Hermit/src/Hermit/resultset/HermitProcedureResultSet.php

    r20417 r20492  
    44 * @author nowelium 
    55 */ 
    6 class HermitProcedureResultSet implements HermitResultSet, HermitParameterBind { 
     6class HermitProcedureResultSet implements HermitResultSet { 
    77    protected $procParameter; 
    88    public function __construct(HermitProcedureParameter $procParameter){ 
     
    1010    } 
    1111    public function execute(HermitStatement $stmt, HermitValueType $type){ 
     12        if($stmt->columnCount() < 1){ 
     13            $stmt->closeCursor(); 
     14            unset($stmt); 
     15            return null; 
     16        } 
    1217        $type->apply($stmt); 
    1318 
    14         if($stmt->columnCount() < 1){ 
    15             return null; 
    16         } 
     19//        $rows = array(); 
     20//        while($row = $stmt->fetch()){ 
     21//            $rows[] = $row; 
     22//        } 
     23//        if(!$stmt->nextRowset()){ 
     24//            return $rows; 
     25//        } 
     26// 
     27//        $results = array(); 
     28//        $results[] = $rows; 
     29//        do { 
     30//            $rows = array(); 
     31//            while($row = $stmt->fetch()){ 
     32//                $rows[] = $row; 
     33//            } 
     34//            $results[] = $rows; 
     35//        } while($stmt->nextRowset()); 
     36// 
     37//        $stmt->closeCursor(); 
     38//        unset($stmt); 
     39//        return $results; 
    1740 
     41        // multiresult so always to array[array] 
    1842        $results = array(); 
    1943        do { 
    20             $row = $stmt->fetch(); 
    21             if(false === $row){ 
    22                 break; 
     44            $rows = array(); 
     45            while($row = $stmt->fetch()){ 
     46                $rows[] = $row; 
    2347            } 
    24             $results[] = $row; 
     48            $results[] = $rows; 
    2549        } while($stmt->nextRowset()); 
     50         
     51        $stmt->closeCursor(); 
     52        unset($stmt); 
    2653        return $results; 
    2754    } 
    28     public function bindParameter(PDO $pdo, array $parameter){ 
    29     } 
    3055} 
  • lang/php/misc/Hermit/src/Hermit/resultset/HermitProcedureResultSetFactory.php

    r20417 r20492  
    1111        // nop 
    1212    } 
    13     public function create(PDO $pdo, HermitProcedureParameter $parameter){ 
     13    public static function create(PDO $pdo, HermitProcedureParameter $parameter){ 
    1414        $dbms = HermitDatabaseMetaFactory::getDbms($pdo); 
    1515        $rs = null; 
  • lang/php/misc/Hermit/src/Hermit/statement/HermitProcedureStatementBuilder.php

    r20417 r20492  
    55 */ 
    66class HermitProcedureStatementBuilder extends HermitStatementBuilder { 
    7     private $method; 
    8     private $annote; 
    9     private $sqlCreator; 
     7    protected $method; 
     8    protected $annote; 
     9    protected $sqlCreator; 
    1010 
    1111    protected static $procedureParameters = array( 
     
    1414 
    1515    public function __construct(ReflectionMethod $method, HermitAnnote $annote, HermitSqlCreator $sqlCreator){ 
     16        parent::__construct($method, $sqlCreator); 
    1617        $this->method = $method; 
    1718        $this->annote = $annote; 
     
    3435            $parameter = new HermitProcedureParameter($info, $dbms); 
    3536        } 
    36         $sql = $this->sqlCreator->createSql($pdo); 
    37         $sql = self::preparedSql($parameter, $sql); 
    38         return new HermitStatement($parameter, $pdo->prepare($sql)); 
     37         
     38        $sql = self::preparedSql($parameter, $this->sqlCreator->createSql()); 
     39        return new HermitDefaultStatement($parameter, $pdo->prepare($sql)); 
    3940    } 
    4041     
  • lang/php/misc/Hermit/src/Hermit/statement/HermitStatement.php

    r20387 r20492  
    44 * @author nowelium 
    55 */ 
    6 class HermitStatement { 
    7     protected $parameter; 
    8     protected $statement; 
    9     public function __construct(HermitSqlParameter $parameter, PDOStatement $statement){ 
    10         $this->parameter = $parameter; 
    11         $this->statement = $statement; 
    12     } 
    13     public function getSqlParameter(){ 
    14         return $this->parameter; 
    15     } 
    16     public function execute($parameterValue = array()){ 
    17         $this->parameter->bind($this->statement, $parameterValue); 
    18         return $this->statement->execute(); 
    19     } 
    20     public function fetch(){ 
    21         $args = func_get_args(); 
    22         $c = count($args); 
    23         if($c < 1){ 
    24             return $this->statement->fetch(); 
    25         } 
    26         if($c < 2){ 
    27             return $this->statement->fetch($args[0]); 
    28         } 
    29         return call_user_func_array(array($this->statement, 'fetch'), $args); 
    30     } 
    31     public function __call($name, $params){ 
    32         return call_user_func_array(array($this->statement, $name), $params); 
    33     } 
     6interface HermitStatement { 
     7    public function getSqlParameter(); 
     8    public function execute($parameterValue = array()); 
     9    public function __call($name, $params); 
    3410} 
  • lang/php/misc/Hermit/src/Hermit/statement/HermitStatementBuilder.php

    r20387 r20492  
    55 */ 
    66class HermitStatementBuilder { 
    7     const REGEX = '/(\/\*([^\*\/]*)\*\/)(\w+|((\'|")([^(\'|")]*)(\'|")))?/m'; 
     7    const SQL_COMMENT_REGEXP = '/(\/\*([^\*\/]*)\*\/)(\w+|((\'|")([^(\'|")]*)(\'|")))?/m'; 
    88    private $method; 
    99    private $sqlCreator; 
     
    1616        $sql = $this->sqlCreator->createSql($pdo); 
    1717        $sql = self::preparedSql($parameter, $sql); 
    18         return new HermitStatement($parameter, $pdo->prepare($sql)); 
     18        return new HermitDefaultStatement($parameter, $pdo->prepare($sql)); 
    1919    } 
    2020 
    2121    protected static function preparedSql(HermitSqlParameter $parameter, $sql){ 
    22         return preg_replace_callback(self::REGEX, array($parameter, 'match'), $sql); 
     22        return preg_replace_callback(self::SQL_COMMENT_REGEXP, array($parameter, 'match'), $sql); 
    2323    } 
    2424 
  • lang/php/misc/Hermit/test/HermitProcedure_mysqlTest.php

    r20417 r20492  
    66    const callIN_OUT_PROCEDURE = 'PROC_IN_OUT'; 
    77    public function callIN_OUT(HermitParam $param); 
     8 
     9    const callINOUT_PROCEDURE = 'PROC_INOUT'; 
     10    public function callINOUT(HermitParam $param); 
     11 
     12    const callIN_OUT_OUT_PROCEDURE = 'PROC_IN_OUT_OUT'; 
     13    public function callIN_OUT_OUT(HermitParam $param); 
     14 
     15    const callIN_MULTI_PROCEDURE = 'PROC_IN_MULTIRESULT'; 
     16    const callIN_MULTI_VALUE_TYPE = 'OBJ'; 
     17    public function callIN_MULTI(HermitParam $param); 
     18 
     19    const callIN_IN_MULTI_PROCEDURE = 'PROC_IN_IN_MULTIRESULT'; 
     20    const callIN_IN_MULTI_VALUE_TYPE = 'ASSOC'; 
     21    public function callIN_IN_MULTI(HermitParam $param); 
     22 
     23    const callIN_OUT_MULTI_PROCEDURE = 'PROC_IN_OUT_MULTIRESULT'; 
     24    const callIN_OUT_MULTI_VALUE_TYPE = 'OBJ'; 
     25    public function callIN_OUT_MULTI(HermitParam $param); 
     26 
     27    const callINOUT_MULTI_PROCEDURE = 'PROC_INOUT_MULTIRESULT'; 
     28    const callINOUT_MULTI_VALUE_TYPE = 'OBJ'; 
     29    public function callINOUT_MULTI(HermitParam $param); 
     30 
     31    const callOUT_MULTI_PROCEDURE = 'PROC_OUT_MULTIRESULT'; 
     32    const callOUT_MULTI_VALUE_TYPE = 'OBJ'; 
     33    public function callOUT_MULTI(HermitParam $param); 
     34 
     35    const callNOSPEC_PARAM_PROCEDURE = 'PROC_NOSPEC_PARAM'; 
     36    const callNOSPEC_PARAM_VALUE_TYPE = 'OBJ'; 
     37    public function callNOSPEC_PARAM(HermitParam $param); 
    838} 
    939 
     
    2151    $param->sales = 1000; 
    2252    $param->tax = -1; 
     53 
    2354    $result = $hermit->callIN_OUT($param); 
    2455 
     
    2758    $test->ok($result === null); 
    2859} 
     60{ 
     61    $param = new HermitParam; 
     62    $param->sales = 5000; 
     63 
     64    $result = $hermit->callINOUT($param); 
     65 
     66    $test->ok($result === null); 
     67    $test->is($param->sales, 1000); 
     68 
     69    $result2 = $hermit->callINOUT($param); 
     70    $test->ok($result === null); 
     71    $test->is($param->sales, 200); 
     72} 
     73{ 
     74    $param = new HermitParam; 
     75    $param->sales = 300; 
     76 
     77    $result = $hermit->callIN_OUT_OUT($param); 
     78    $test->ok($result === null); 
     79    $test->ok($param->tax !== null); 
     80    $test->ok($param->total !== null); 
     81    $test->is($param->tax, 60); 
     82    $test->is($param->total, 360); 
     83} 
     84{ 
     85    $param = new HermitParam; 
     86    $param->set('IN_MGR', 7902); 
     87 
     88    $result = $hermit->callIN_MULTI($param); 
     89    $test->ok(is_array($result)); 
     90    $test->is(count($result), 3); 
     91    // same results... 0 to 3 
     92    { 
     93        $test->is(count($result[0]), 1); 
     94        $rs = $result[0][0]; 
     95        $test->is($rs->EMPNO, 7369); 
     96        $test->is($rs->ENAME, 'SMITH'); 
     97        $test->is($rs->JOB, 'CLERK'); 
     98    } 
     99    { 
     100        $test->is(count($result[1]), 1); 
     101        $rs = $result[1][0]; 
     102        $test->is($rs->EMPNO, 7369); 
     103        $test->is($rs->ENAME, 'SMITH'); 
     104        $test->is($rs->JOB, 'CLERK'); 
     105    } 
     106    { 
     107        $test->is(count($result[2]), 1); 
     108        $rs = $result[2][0]; 
     109        $test->is($rs->EMPNO, 7369); 
     110        $test->is($rs->ENAME, 'SMITH'); 
     111        $test->is($rs->JOB, 'CLERK'); 
     112    } 
     113} 
     114{ 
     115    $param = new HermitParam; 
     116    $param->set('IN_MGR_1', '7698'); 
     117    $param->set('IN_MGR_2', '7902'); 
     118 
     119    $result = $hermit->callIN_IN_MULTI($param); 
     120