diff --git a/db/mysql/PoolPDO.php b/db/mysql/PoolPDO.php index 322a71f..65e528b 100644 --- a/db/mysql/PoolPDO.php +++ b/db/mysql/PoolPDO.php @@ -111,6 +111,7 @@ public function doQuery($sql,$isExecute = false, $method, $fetchMode) /** * @param $data * @param $fetchMode + * @deprecated it instead by PDOStatement * @return bool */ protected function fetch($data,$fetchMode) @@ -126,6 +127,7 @@ protected function fetch($data,$fetchMode) /** * @param $data * @param $fetchMode + * @deprecated it instead by PDOStatement * @return array */ protected function fetchAll($data,$fetchMode) @@ -144,6 +146,7 @@ protected function fetchAll($data,$fetchMode) /** * @param $data * @param $fetchMode + * @deprecated it instead by PDOStatement * @return mixed|null */ protected function fetchColumn($data,$fetchMode) @@ -163,6 +166,11 @@ public function lastInsertId($name = null) return $this->_lastInsertId; } + public function setLastInsertId($value) + { + return $this->_lastInsertId = $value; + } + /** * @param int $attribute * @return mixed|null @@ -194,7 +202,7 @@ public function quote($string, $parameter_type = PDO::PARAM_STR) if ($parameter_type !== PDO::PARAM_STR) { throw new PDOException('Only PDO::PARAM_STR is currently implemented for the $parameter_type of MysqlPoolPdo::quote()'); } - return "'" . str_replace("'", "''", $string) . "'"; + return $this->pool->escape($string); } /** @@ -242,6 +250,7 @@ public function commit() } $ret = $this->pool->commit($this->_bingId); $this->_bingId = null; + $this->_isTransaction = false; return $ret; } /** @@ -256,6 +265,7 @@ public function rollBack() } $ret = $this->pool->rollBack($this->_bingId); $this->_bingId = null; + $this->_isTransaction = false; return $ret; } @@ -264,8 +274,7 @@ public function onError($event) if($this->_bingId === null){ return ; } - $this->pool->rollBack($this->_bingId); - $this->_bingId = null; + $this->rollBack(); } /** diff --git a/db/mysql/PoolPDOStatement.php b/db/mysql/PoolPDOStatement.php index 80bd664..f3558f1 100644 --- a/db/mysql/PoolPDOStatement.php +++ b/db/mysql/PoolPDOStatement.php @@ -16,35 +16,37 @@ */ class PoolPDOStatement extends PDOStatement { - protected $_sth; + protected $statement; /** * PDO Oci8 driver * * @var PoolPDO */ - protected $_pdo; + protected $pdo; /** * Statement options * * @var array */ - protected $_options = array(); + protected $options = array(); /** * Default fetch mode for this statement * @var integer */ - protected $_fetchMode = null; + private $_fetchMode = null; /** * @var ResultData */ - protected $_result = null; + private $_resultData = null; - protected $_boundColumns = []; + private $_boundColumns = []; + + private $_index = 0; /** * PoolPDOStatement constructor. @@ -54,11 +56,20 @@ class PoolPDOStatement extends PDOStatement */ public function __construct(string $statement,PoolPDO $pdo, $options) { - $this->_sth = $statement; - $this->_pdo = $pdo; - $this->_options = $options; + $this->statement = $statement; + $this->pdo = $pdo; + $this->options = $options; + } + + /** + * @inheritdoc + */ + function __destruct() + { + unset($this->_resultData,$this->_boundColumns,$this->statement); } + /** * Executes a prepared statement * @@ -68,26 +79,33 @@ public function __construct(string $statement,PoolPDO $pdo, $options) */ public function execute($inputParams = []) { - $bingID = $this->_pdo->getBingId(); - $pool = $this->_pdo->pool; + $bingID = $this->pdo->getBingId(); + $pool = $this->pdo->pool; if(!empty($inputParams)){ $this->_boundColumns = $inputParams; } if(!empty($this->_boundColumns)){ $this->prepareParamName(); - $this->_result = $pool->prepareAndExecute($this->_sth,$this->_boundColumns,$bingID); + $this->_resultData = $pool->prepareAndExecute($this->statement,$this->_boundColumns,$bingID); + $this->pdo->setLastInsertId($this->_resultData->insert_id); }else{ - $this->_result = $pool->doQuery($this->_sth,$bingID); + $this->_resultData = $pool->doQuery($this->statement,$bingID); + } + if($this->_resultData->result === false){ + throw new PDOException($this->_resultData->error); } return true; } public function prepareParamName() { - $statement = $this->_sth; + $statement = $this->statement; if (strpos($statement, ':') !== false) { $data = []; - $this->_sth = preg_replace_callback('/:\w+\b/u', function ($matches) use (&$data) { + $this->statement = preg_replace_callback('/:\w+\b/u', function ($matches) use (&$data) { + if(!isset($this->_boundColumns[$matches[0]])){ + return $matches[0]; + } $data[] = $this->_boundColumns[$matches[0]]; return '?'; }, $statement); @@ -112,17 +130,37 @@ public function fetch( $cursor_offset = 0 ) { + static $styleUnsupport = [ + 'PDO::FETCH_BOUND' => PDO::FETCH_BOUND, + 'PDO::FETCH_CLASS' => PDO::FETCH_CLASS, + 'PDO::FETCH_INTO' => PDO::FETCH_INTO, + 'PDO::FETCH_LAZY' => PDO::FETCH_LAZY, + 'PDO::FETCH_NAMED' => PDO::FETCH_NAMED, + 'PDO::FETCH_OBJ' => PDO::FETCH_OBJ, + ]; if ($cursor_orientation !== PDO::FETCH_ORI_NEXT || $cursor_offset !== 0) { throw new PDOException('$cursor_orientation that is not PDO::FETCH_ORI_NEXT is not implemented for PoolPDOStatement::fetch()'); } - - if($fetch_style == PDO::FETCH_CLASS) { - throw new PDOException('PDO::FETCH_CLASS is not implemented for PoolPDOStatement::fetch()'); + if(in_array($fetch_style,$styleUnsupport)) { + throw new PDOException(array_search($fetch_style,$styleUnsupport).'is not implemented for PoolPDOStatement::fetch()'); } - if(empty($this->_result)){ + + if( + empty($this->_resultData) + || empty($result = $this->_resultData->result) + || empty($data = $result[$this->_index++] ?? []) + ){ return false; } - return $this->_result->result[0]; + + if($fetch_style == PDO::FETCH_NUM){ + $data = array_values($data); + }elseif ($fetch_style == PDO::FETCH_BOTH){ + $dataRows = array_values($data); + $data = array_merge($data,$dataRows); + } + + return $data; } /** @@ -199,10 +237,10 @@ public function bindValue( */ public function rowCount() { - if(empty($this->_result)){ + if(empty($this->_resultData)){ return 0; } - return $this->_result->affected_rows; + return $this->_resultData->affected_rows; } /** @@ -214,10 +252,11 @@ public function rowCount() */ public function fetchColumn($colNumber = 0) { - if( empty($this->_result->result[$colNumber]) ){ + $result = $this->fetch(PDO::FETCH_NUM); + if ($result === false) { return false; } - return array_shift($this->_result->result[$colNumber]); + return $result[$colNumber] ?? false; } /** @@ -235,15 +274,16 @@ public function fetchAll( $ctor_args = null ) { - if(empty($this->_result)){ + if(empty($this->_resultData) || empty($this->_resultData->result)){ return []; } if($fetch_style == PDO::FETCH_COLUMN){ - $keys = array_keys($this->_result->result[0]); + $keys = array_keys($this->_resultData->result[0]); $key = array_shift($keys); - return ArrayHelper::getColumn((array)$this->_result->result,$key); + unset($keys); + return ArrayHelper::getColumn((array)$this->_resultData->result,$key); } - return $this->_result->result; + return $this->_resultData->result; } /** @@ -271,7 +311,7 @@ public function fetchObject($className = 'stdClass', $ctor_args = null) */ public function errorCode() { - return $this->_result->errno; + return $this->_resultData->errno; } /** @@ -281,11 +321,11 @@ public function errorCode() */ public function errorInfo() { - if ($this->_result->errno) { + if ($this->_resultData->errno) { return array( 'HY000', - $this->_result->errno, - $this->_result->error + $this->_resultData->errno, + $this->_resultData->error ); } @@ -302,7 +342,7 @@ public function errorInfo() */ public function setAttribute($attribute, $value) { - $this->_options[$attribute] = $value; + $this->options[$attribute] = $value; return true; } @@ -315,8 +355,8 @@ public function setAttribute($attribute, $value) */ public function getAttribute($attribute) { - if (isset($this->_options[$attribute])) { - return $this->_options[$attribute]; + if (isset($this->options[$attribute])) { + return $this->options[$attribute]; } return null; } @@ -328,11 +368,11 @@ public function getAttribute($attribute) */ public function columnCount() { - if(empty($this->_result) || empty($this->_result->result)){ + if(empty($this->_resultData) || empty($this->_resultData->result)){ return 0; } - return count(@$this->_result->result[0]); + return count(@$this->_resultData->result[0]); } public function getColumnMeta($column) @@ -382,7 +422,7 @@ public function nextRowset() */ public function closeCursor() { - unset($this->_result); + unset($this->_resultData); return true; } diff --git a/pool/MysqlPool.php b/pool/MysqlPool.php index 4a949f4..e02bd3c 100644 --- a/pool/MysqlPool.php +++ b/pool/MysqlPool.php @@ -40,7 +40,7 @@ public function init() $this->mysqlConfig = array_merge($this->defaultMysqlConfig,$this->mysqlConfig); $this->poolQueue = new \SplQueue(); for($i = 0;$i<$this->minSize;$i++){ - $conenct = $this->getConnect(); + $conenct = $this->openOneConnect(); $this->releaseConnect($conenct); } parent::init(); @@ -95,9 +95,17 @@ public function prepareAndExecute(string $sql, array $inputParams = [], $bindID $connect = $this->getConnect(); } $res = false; + $stmt = null; try{ $stmt = $connect->prepare($sql); $stmt && $res = $stmt->execute($inputParams); + + /** + * it is better to use statement object once, + * I do not want to provide any Socket-Resources to the developer, + * by a thought as all Link-Resources is the devils to some lovely developer. + */ + unset($stmt); }catch (\Exception $exception){ throw $exception; }finally{ @@ -112,10 +120,37 @@ public function prepareAndExecute(string $sql, array $inputParams = [], $bindID ]); } + public function escape(string $string) : string + { + $connect = $this->getConnect(); + $res = null; + try{ + if(method_exists($connect,'escape')){ + $res = $connect->escape($string); + }else{ + \Yii::warning("MysqlPool::escape() is not effected! please check swoole compile option [--enable-mysqlnd]"); + $res = "'" . str_replace("'", "''", $string) . "'"; + } + }catch (\Exception $exception){ + throw $exception; + }finally{ + $this->releaseConnect($connect); + } + return $res ?? $string; + } + public function begin() { $connect = $this->getConnect(); - if(!$connect->query("begin;")){ + $res = false; + try{ + $res = $connect->begin(); + }catch (\Exception $exception){ + throw $exception; + }finally{ + $this->releaseConnect($connect); + } + if($res === false){ return false; } return (string) $connect->sock; @@ -126,7 +161,7 @@ public function commit($bindID) $connect = $this->getBindConnect($bindID); $res = false; try{ - $res = $connect->query("commit;"); + $res = $connect->commit(); }catch (\Exception $exception){ throw $exception; }finally{ @@ -140,7 +175,7 @@ public function rollBack($bindID) $connect = $this->getBindConnect($bindID); $res = false; try{ - $res = $connect->query("rollback;"); + $res = $connect->rollback(); }catch (\Exception $exception){ throw $exception; }finally{