<?php
/*
* Copyright (C) 2002-2004
* @author chenxi
* @version $Id: Statement.class.php,v 0.1 2004/11/04 11:34:03
*/
require_once ('Object.class.php');
require_once ('pdbc/mysql/ResultSet.class.php');
require_once ('util/StringBuffer.class.php');
require_once ('util/StringUtils.class.php');
define ('CLOSE_ALL_RESULTS', 0);
define ('KEEP_CURRENT_RESULT', 1);
define ('CLOSE_CURRENT_RESULT', 2);
class mysql_Statement extends Object {
/* µ±Ç°¶ÔÏóid */
var $id = null;
/* Êý¾Ý¿âÁ¬½Ó */
var $conn = null;
/* ½á¹û¼¯ */
var $result = false;
/* ±¾´Î»á»°µÄÅúÁ¿²éѯÓï¾ä¼¯ºÏ */
var $sqlBatch = null;
/* ±¾´Î»á»°µÄÅúÁ¿²éѯ½á¹û¼¯¼¯ºÏ */
var $resultBatch = null;
/* µ±Ç°ÅúÁ¿²éѯ½á¹û¼¯µÄÓαê */
var $current_result_offset = 0;
/* µ±Ç°µÄ²éѯ½á¹û¼¯ */
var $currentResult = null;
/* Óɵ±Ç°Statement¶ÔÏó´´½¨µÄResultSet¶ÔÏó¼¯ºÏ */
var $openResults = null;
/* µ±Ç°»á»°µÄ²éѯ½á¹û¼¯ */
var $resultSet = null;
/* ±¾´Î»á»°µÄ²éѯÓï¾äÊÇ·ñÊÇSELECTÓï¾äµÄ±êʶ */
var $isSelect = true;
/* µ±Ç°Statement¶ÔÏóÊÇ·ñÒѹرյıêʶ */
var $isClosed = false;
/* ²éѯ½á¹û¼¯µÄfetch´óС */
var $fetchSize = 30;
/* ²éѯ³¬Ê±Ê±¼ä */
var $queryTimeout = 30;
/* ×îºóÒ»´Î²éѯµÄSQLÓï¾ä */
var $lastSql = null;
/**
* ¹¹Ô캯Êý
*/
function &mysql_Statement(&$conn) {
$this->id = $this->genUniqueId();
$this->conn = $conn;
}
/**
* Îö¹¹º¯Êý
*/
function __destruct() {
$this->conn = null;
$this->resultSet = null;
$this->isClosed = true;
}
/*
* ½«¸ø¶¨µÄsqlÃüÁîÌí¼Óµ½µ±Ç°Statement¶ÔÏóµÄsqlÃüÁîÁбíÖÐ
* @return void
*/
function addBatch($sql) {
if (!$this->sqlBatch) {
$this->sqlBatch = array();
}
if (is_array($sql)) {
foreach ($sql as $num => $s) {
if ($sql)
$this->sqlBatch[sizeof($this->sqlBatch)] = $sql[$num];
}
} else {
if ($sql)
$this->sqlBatch[sizeof($this->sqlBatch)] = $sql;
}
}
function cancel() {
//not implement
}
/**
* ¼ì²éµ±Ç°Êý¾Ý¿âÁ¬½ÓÊÇ·ñÒѹرÕ
*/
function checkClosed() {
if ($this->isClosed())
$this->throws('No operations allowed after Statement closed.', E_USER_ERROR);
}
/**
* @param SQLÓï¾ä
* ¼ì²ésqlÊÇ·ñΪ¿Õ
*/
function checkNullOrEmptyQuery($sql=null) {
if (null === $sql)
trigger_error('sql is null', E_USER_ERROR);
if ((int)0 == strlen($sql))
trigger_error('sql length is 0', E_USER_ERROR);
}
/**
* Çå¿Õµ±Ç°ÅúÁ¿²éѯµÄËùÓÐÐÅÏ¢
* return void
* @access public
*/
function clearBatch() {
$this->clearBatchResult();
$this->clearBatchSQL();
}
/**
* Çå¿ÕÅúÁ¿²éѯµÄ½á¹û¼¯ÒÔ¼°ÅúÁ¿²éѯSQLÓï¾ä(¿ÉÑ¡)
* @param boolean $clearSQL ÊÇ·ñÇå¿ÕÅúÁ¿²éѯSQLÓï¾ä
* @return void
* @access private
*/
function clearBatchResult($offset=0) {
if ($offset >= sizeof($this->resultBatch)) {
$this->throws($offset.' is overflow of sizeof($this->resultBatch)', null);
return;
}
for ($i = $offset; $i < sizeof($this->resultBatch); $i++) {
if (is_resource($this->resultBatch[$i]))
mysql_free_result($this->resultBatch[$i]);
}
$this->resultBatch = null;
}
/**
* Çå¿ÕÅúÁ¿²éѯSQLÓï¾ä
* @param boolean $clear ÊÇ·ñÇå¿ÕÅúÁ¿²éѯSQLÓï¾ä
* @return void
* @access private
*/
function clearBatchSQL($clear=false) {
if ($clear)
$this->sqlBatch = null;
}
/**
* Êͷŵ±Ç°µÄ²éѯ
*/
function close() {
$this->realClose(true);
}
/**
* ¹Ø±Õµ±Ç°ËùÓлµÄResultSet¶ÔÏó
* @return void
* @access private
*/
function closeAllOpenResults() {
if (null !== $this->openResults) {
for ($i = 0; $i < $this->openResults->size(); $i++) {
$currentOpenResult = $this->openResults->get($i);
$ret = $currentOpenResult->realClose();
if (is_a($ret, 'EXCEPTION'))
$exp = $ret;
}
if (isset($exp))
$this->throws($exp->getMessage(), $exp->getCode(), $exp->getMode());
}
}
/**
* Document me
* @return void
* @access private
*/
function closeAllOpenResult() {
if (null !== $this->resultBatch) {
foreach ($this->resultBatch as $num => $rs) {
if (is_object($rs) && is_a($rs, 'mysql_ResultSet')) {
$rs->close();
}
}
}
$this->resultBatch = null;
}
/**
* Ö´ÐÐSQLÓï¾ä
* @see com.shine.pdbc.mysql.mysql_PreparedStatement.executeQuery() OR
* com.shine.pdbc.mysql.mysql_PreparedStatement.executeUpdate()
* @return com.shine.pdbc.mysql.mysql_ResultSet;
* true³É¹¦£¬falseʧ°Ü;
*/
function execute($sql) {
$this->checkNullOrEmptyQuery($sql);
$this->checkClosed();
$firstNonWsChar = StringUtils::firstNonWsChar($sql);
if ('S' != $firstNonWsChar) {
$this->isSelect = false;
if ($this->conn->isReadOnly())
return false;
#trigger_error('Connection is in readonly mode', E_USER_ERROR);
$this->executeUpdate($sql);
}
return $this->executeQuery($sql);
}
/*
* Ö´ÐÐÅúÁ¿²éѯ
* @return int[] update counts
*/
function executeBatch() {
if (!is_array($this->sqlBatch) || (int)0 == sizeof($this->sqlBatch)) {
$errbuf = new StringBuffer('no sql in Batch');
$this->throws($errbuf->toString(), null, EXCEPTION_DIE, NULL, 'Exceptions', __FILE__, __LINE__);
}
$updateCounts = array();
foreach ($this->sqlBatch as $num => $sql) {
if ($sql) {
if (!$this->realExecuteSQL($sql)) {
$updateCounts[$num] = -1;
$this->resultBatch[$num] = false;
} else {
/*
print $num.': ';
var_dump($this->result);
print '<br/>';
*/
if (is_resource($this->result)) {
$this->resultBatch[$num] = $this->getResultSet();
/*
print $num.': ';
var_dump($this->resultBatch[$num]);
print '<br/>';
*/
} else {
$this->resultBatch[$num] = $this->result;
}
$updateCounts[$num] = $this->getUpdateCount();
}
}
}
return $updateCounts;
}
/**
* Ö´ÐÐSELECT²éѯ
* @return mysql_ResultSet
*/
function executeQuery($sql) {
if ($GLOBALS['debug'] && (int)4 >= $GLOBALS['debug'])
$this->debug($sql);
$this->realExecuteSQL($sql);
return $this->getResultSet();
}
/**
* Ö´ÐÐINPUT, UPDATE, DELETEµÈSQLÓï¾ä
* @return boolean true/false
*/
function executeUpdate($sql) {
if ($GLOBALS['debug'] && (int)4 >= $GLOBALS['debug'])
$this->debug($sql);
return $this->realExecuteSQL($sql);
}
/**
* ·µ»Øµ±Ç°¶ÔÏóµÄid
* @access public
* @see Object->genUniqueId()
*/
function getId() {
return $this->id;
}
/**
* Ö´ÐлỰÆÚ¼äÄڵIJéѯ
* @return Object mysqlh_ResultSet
* @return boolean true/false
*/
function realExecuteSQL($sql) {
$firstNonWsChar = StringUtils::firstNonWsChar($sql);
if ('S' != $firstNonWsChar) {
$this->isSelect = false;
if ($this->conn->isReadOnly())
#trigger_error('Connection is in readonly mode', E_USER_WARNING);
return false;
}
$this->lastSql = $sql;
$result = mysql_query($sql);
if ($GLOBALS['debug'] && (int)3 >= $GLOBALS['debug'])
var_dump($result);
if ($result) {
$this->result = $result;
return true;
}
/*
else {
$errbuf = new StringBuffer();
$errbuf->append('Error - SQLSTATE '.mysql_errno($this->conn->getConnection()));
$errbuf->append(': ');
$errbuf->append(mysql_error($this->conn->getConnection()));
return new Error($errbuf->toString(), null, ERROR_DIE);
}
*/
return false;
}
/**
* »ñÈ¡ÅúÁ¿Ö´ÐеÄSQLÁбí
* @return Array $sqlBatch
*/
function getBatchSQL() {
return $this->sqlBatch;
}
/**
* »ñÈ¡Êý¾Ý¿âÁ¬½Ó
* @return resource $conn
*/
function getConnection() {
return $this->conn->getConnection();
}
/**
* »ñÈ¡fetchsize
* @return void
*/
function getFetchSize() {
return $this->fetchSize;
}
/**
* ´òÓ¡µ±Ç°Statement¶ÔÏóµÄfetchsize
* @return String
*/
function pGgetFetchSize() {
printf ('Fetch Size: %s<br/>', $this->fetchSize);
}
/**
* ·µ»Ø²éѯ³¬Ê±Ê±¼ä
* @return int queryTimeout
*/
function getQueryTimeout() {
return $this->queryTimeout;
}
/**
* ÒÆ¶¯µ½µ±Ç°Statement¶ÔÏóµÄÏÂÒ»¸öResultSet¶ÔÏó
* @param integer
* @return boolean
*/
function getMoreResults($current=CLOSE_CURRENT_RESULT) {
switch ($current) {
case CLOSE_CURRENT_RESULT :
if (null !== $this->currentResult && is_object($this->currentReuslt))
$this->currentResult->close();
break;
case CLOSE_ALL_RESULTS :
if (null !== $this->currentResult && is_object($this->currentReuslt))
$this->currentResult->close();
$this->closeAllOpenResult();
break;
case KEEP_CURRENT_RESULT :
//do nothing
break;
}
$this->resultSet = $this->getNextResult();
return (is_object($rs) && is_a($rs, 'mysql_ResultSet')) ? true: false;
/*
foreach ($this->resultBatch as $num => $rs) {
if (is_object($rs) && is_a($rs, 'mysql_ResultSet')) {
$this->resultSet = $rs;
$this->current_result_offset = $i;
return true;
} else {
$this->current_result_offset = $i;
return false;
}
}
*/
}
/**
* »ñÈ¡µ±Ç°¶ÔÏóÖеÄÏÂÒ»¸ö½á¹û¼¯
* @return mysql_ResultSet
* @access private
*/
function getNextResult() {
return $this->resultBatch[$this->current_result_offset++];
}
/**
* »ñÈ¡±¾´Î»á»°µÄ²éѯ½á¹û¼¯
* @return mysql_ResultSet
* @access public
*/
function getResultSet() {
if (is_object($this->resultSet) && is_a($this->resultSet, 'mysql_ResultSet')) {
return $this->resultSet;
} else if (is_resource($this->result)) {
return new mysql_ResultSet($this->result);
} else {
return null;
}
}
/**
* ·µ»ØÊÜÓ°ÏìµÄ¼Ç¼Êý
* @return int
* @access public
*/
function getUpdateCount() {
if (!$this->isSelect && is_bool($this->result))
return mysql_affected_rows($this->conn->getConnection());
return -1;
}
/**
* Document me
*/
function getWarnings() {
//not implement yet
}
/**
* ·µ»Øµ±Ç°Statement¶ÔÏóÊÇ·ñÒѹرյıêʶ
* @return boolean
*/
function isClosed() {
return $this->isClosed;
}
/**
* ¹Ø±Õµ±Ç°Statement¶ÔÏó
* @param boolean $calledExplicitly
* @return void
*/
function realClose($calledExplicitly=false) {
if ($this->isClosed)
return;
$this->closeAllOpenResults();
$this->openResults = null;
$this->result = null;
$this->resultSet = null;
$this->isClosed = true;
}
/**
* ÉèÖõ±Ç°²éѯµÄ½á¹û¼¯size
* @param numeric $fetchSize
* @return void
*/
function setFetchSize($fetchSize) {
$fetchSize = StringUtils::isNumeric($fetchSize);
if (!$fetchSize)
trigger_error($fetchSize.' is not a numeric', E_USER_ERROR);
$this->fetchSize = $fetchSize;
}
/**
* ÉèÖòéѯ³¬Ê±Ê±³¤
* @param numeric $timeout
* @return void
*/
function setQueryTimeout($timeout) {
$timeout = StringUtils::isNumeric($timeout);
if ($timeout) {
$this->queryTimeout = $timeout;
ini_set('mysql.connect_timeout', $timeout);
} else {
$this->queryTimeout = 60;
}
}
}
?>