PreparedStatementCommon.php

Go to the documentation of this file.
00001 <?php 00002 /* 00003 * $Id: PreparedStatementCommon.php,v 1.6 2004/04/13 12:23:02 hlellelid Exp $ 00004 * 00005 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00006 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00007 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 00008 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 00009 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00010 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 00011 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00012 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00013 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00014 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00015 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00016 * 00017 * This software consists of voluntary contributions made by many individuals 00018 * and is licensed under the LGPL. For more information please see 00019 * <http://creole.phpdb.org>. 00020 */ 00021 00034 abstract class PreparedStatementCommon { 00035 00040 protected $conn; 00041 00046 protected $limit = 0; 00047 00053 protected $offset = 0; 00054 00059 protected $sql; 00060 00065 protected $positions; 00066 00067 00072 protected $positionsCount; 00073 00078 protected $boundInVars = array(); 00079 00084 protected $resultSet; 00085 00090 protected $updateCount; 00091 00100 function __construct(Connection $conn, $sql) 00101 { 00102 $this->conn = $conn; 00103 $this->sql = $sql; 00104 00105 // get the positiosn for the '?' in the SQL 00106 // we can move this into its own method if it gets more complex 00107 $positions = array(); 00108 $position = 0; 00109 $positionsCount = 0; 00110 while( $position < strlen($sql) && ($question = strpos($sql, '?', $position)) !== false ) { 00111 $positions[] = $question; 00112 $position = $question + 1; 00113 $positionsCount++; 00114 } 00115 00116 $this->positions = $positions; 00117 $this->positionsCount = $positionsCount; // save processing later in cases where we may repeatedly exec statement 00118 } 00119 00123 public function setLimit($v) 00124 { 00125 $this->limit = (int) $v; 00126 } 00127 00131 public function getLimit() 00132 { 00133 return $this->limit; 00134 } 00135 00139 public function setOffset($v) 00140 { 00141 $this->offset = (int) $v; 00142 } 00143 00147 public function getOffset() 00148 { 00149 return $this->offset; 00150 } 00151 00155 public function getResultSet() 00156 { 00157 return $this->resultSet; 00158 } 00159 00163 public function getUpdateCount() 00164 { 00165 return $this->updateCount; 00166 } 00167 00171 public function getMoreResults() 00172 { 00173 if ($this->resultSet) $this->resultSet->close(); 00174 $this->resultSet = null; 00175 return false; 00176 } 00177 00181 public function getConnection() 00182 { 00183 return $this->conn; 00184 } 00185 00191 public function getResource() 00192 { 00193 return null; 00194 } 00195 00199 public function close() 00200 { 00201 } 00202 00211 protected function replaceParams() 00212 { 00213 // Default behavior for this function is to behave in 'emulated' mode. 00214 $sql = ''; 00215 $last_position = 0; 00216 00217 for ($position = 0; $position < $this->positionsCount; $position++) { 00218 if (!isset($this->boundInVars[$position + 1])) { 00219 throw new SQLException('Replace params: undefined query param: ' . ($position + 1)); 00220 } 00221 $current_position = $this->positions[$position]; 00222 $sql .= substr($this->sql, $last_position, $current_position - $last_position); 00223 $sql .= $this->boundInVars[$position + 1]; 00224 $last_position = $current_position + 1; 00225 } 00226 // append the rest of the query 00227 $sql .= substr($this->sql, $last_position); 00228 00229 return $sql; 00230 } 00231 00242 public function executeQuery($p1 = null, $fetchmode = null) 00243 { 00244 $params = null; 00245 if ($fetchmode !== null) { 00246 $params = $p1; 00247 } elseif ($p1 !== null) { 00248 if (is_array($p1)) $params = $p1; 00249 else $fetchmode = $p1; 00250 } 00251 00252 if ($params) { 00253 for($i=0,$cnt=count($params); $i < $cnt; $i++) { 00254 $this->set($i+1, $params[$i]); 00255 } 00256 } 00257 00258 $this->updateCount = null; // reset 00259 $sql = $this->replaceParams(); 00260 00261 if ($this->limit > 0) { 00262 $this->conn->applyLimit($sql, $this->offset, $this->limit); 00263 } elseif ($this->offset > 0) { 00264 throw new SQLException('Cannot specify an offset without limit.'); 00265 } 00266 00267 $this->resultSet = $this->conn->executeQuery($sql, $fetchmode); 00268 return $this->resultSet; 00269 } 00270 00278 public function executeUpdate($params = null) 00279 { 00280 if ($params) { 00281 for($i=0,$cnt=count($params); $i < $cnt; $i++) { 00282 $this->set($i+1, $params[$i]); 00283 } 00284 } 00285 00286 if($this->resultSet) $this->resultSet->close(); 00287 $this->resultSet = null; // reset 00288 $sql = $this->replaceParams(); 00289 $this->updateCount = $this->conn->executeUpdate($sql); 00290 return $this->updateCount; 00291 } 00292 00298 abstract protected function escape($str); 00299 00312 function set($paramIndex, $value) 00313 { 00314 $type = gettype($value); 00315 if ($type == "object") { 00316 if (is_a($value, 'Blob')) { 00317 $this->setBlob($paramIndex, $value); 00318 } elseif (is_a($value, 'Clob')) { 00319 $this->setClob($paramIndex, $value); 00320 } elseif (is_a($value, 'Date')) { 00321 // can't be sure if the column type is a DATE, TIME, or TIMESTAMP column 00322 // we'll just use TIMESTAMP by default; hopefully DB won't complain (if 00323 // it does, then this method just shouldn't be used). 00324 $this->setTimestamp($paramIndex, $value); 00325 } else { 00326 throw new SQLException("Unsupported object type passed to set(): " . get_class($value)); 00327 } 00328 } else { 00329 if ($type == "integer") { 00330 $type = "int"; 00331 } elseif ($type == "double") { 00332 $type = "float"; 00333 } 00334 $setter = 'set' . ucfirst($type); // PHP types are case-insensitive, but we'll do this in case that changes 00335 $this->$setter($paramIndex, $value); 00336 } 00337 } 00338 00347 function setArray($paramIndex, $value) 00348 { 00349 if ($value === null) { 00350 $this->setNull($paramIndex); 00351 } else { 00352 $this->boundInVars[$paramIndex] = "'" . $this->escape(serialize($value)) . "'"; 00353 } 00354 } 00355 00363 function setBoolean($paramIndex, $value) 00364 { 00365 if ($value === null) { 00366 $this->setNull($paramIndex); 00367 } else { 00368 $this->boundInVars[$paramIndex] = (int) $value; 00369 } 00370 } 00371 00372 00376 function setBlob($paramIndex, $blob) 00377 { 00378 if ($blob === null) { 00379 $this->setNull($paramIndex); 00380 } else { 00381 // they took magic __toString() out of PHP5.0.0; this sucks 00382 if (is_object($blob)) { 00383 $blob = $blob->__toString(); 00384 } 00385 $this->boundInVars[$paramIndex] = "'" . $this->escape($blob) . "'"; 00386 } 00387 } 00388 00392 function setClob($paramIndex, $clob) 00393 { 00394 if ($clob === null) { 00395 $this->setNull($paramIndex); 00396 } else { 00397 // they took magic __toString() out of PHP5.0.0; this sucks 00398 if (is_object($clob)) { 00399 $clob = $clob->__toString(); 00400 } 00401 $this->boundInVars[$paramIndex] = "'" . $this->escape($clob) . "'"; 00402 } 00403 } 00404 00410 function setDate($paramIndex, $value) 00411 { 00412 if (is_numeric($value)) $value = date("Y-m-d", $value); 00413 if (is_object($value)) $value = date("Y-m-d", $value->getTime()); 00414 if ($value === null) { 00415 $this->setNull($paramIndex); 00416 } else { 00417 $this->boundInVars[$paramIndex] = "'" . $this->escape($value) . "'"; 00418 } 00419 } 00420 00426 function setDecimal($paramIndex, $value) 00427 { 00428 if ($value === null) { 00429 $this->setNull($paramIndex); 00430 } else { 00431 $this->boundInVars[$paramIndex] = (float) $value; 00432 } 00433 } 00434 00440 function setDouble($paramIndex, $value) 00441 { 00442 if ($value === null) { 00443 $this->setNull($paramIndex); 00444 } else { 00445 $this->boundInVars[$paramIndex] = (double) $value; 00446 } 00447 } 00448 00454 function setFloat($paramIndex, $value) 00455 { 00456 if ($value === null) { 00457 $this->setNull($paramIndex); 00458 } else { 00459 $this->boundInVars[$paramIndex] = (float) $value; 00460 } 00461 } 00462 00468 function setInt($paramIndex, $value) 00469 { 00470 if ($value === null) { 00471 $this->setNull($paramIndex); 00472 } else { 00473 $this->boundInVars[$paramIndex] = (int) $value; 00474 } 00475 } 00476 00482 function setInteger($paramIndex, $value) 00483 { 00484 $this->setInt($paramIndex, $value); 00485 } 00486 00491 function setNull($paramIndex) 00492 { 00493 $this->boundInVars[$paramIndex] = 'NULL'; 00494 } 00495 00501 function setString($paramIndex, $value) 00502 { 00503 if ($value === null) { 00504 $this->setNull($paramIndex); 00505 } else { 00506 // it's ok to have a fatal error here, IMO, if object doesn't have 00507 // __toString() and is being passed to this method. 00508 $value = (is_object($value) ? $value->__toString() : (string) $value); 00509 $this->boundInVars[$paramIndex] = "'" . $this->escape($value) . "'"; 00510 } 00511 } 00512 00518 function setTime($paramIndex, $value) 00519 { 00520 if (is_numeric($value)) $value = date("H:i:s", $value); 00521 elseif (is_object($value)) $value = date("H:i:s", $value->getTime()); 00522 00523 if ($value === null) { 00524 $this->setNull($paramIndex); 00525 } else { 00526 $this->boundInVars[$paramIndex] = "'" . $this->escape($value) . "'"; 00527 } 00528 } 00529 00535 function setTimestamp($paramIndex, $value) 00536 { 00537 if (is_numeric($value)) $value = date('Y-m-d H:i:s', $value); 00538 elseif (is_object($value)) $value = date("Y-m-d H:i:s", $value->getTime()); 00539 00540 if ($value === null) { 00541 $this->setNull($paramIndex); 00542 } else { 00543 $this->boundInVars[$paramIndex] = "'".$value."'"; 00544 } 00545 } 00546 00547 }

This file is part of the Creole[php5] library.


Copyright © 2004 Hans Lellelid  
Creole[php5] CVS