OCI8PreparedStatement Class Reference

Inheritance diagram for OCI8PreparedStatement:

PreparedStatementCommon PreparedStatement

List of all members.

Public Member Functions

 close ()
 If the statement is set, free it.
 executeQuery ($p1=null, $fetchmode=null)
 Executes the SQL query in this PreparedStatement object and returns the resultset generated by the query.
 executeUpdate ($params=null)
 Executes the SQL INSERT, UPDATE, or DELETE statement in this PreparedStatement object.
 setBlob ($paramIndex, $blob)
 setClob ($paramIndex, $clob)
 setString ($paramIndex, $value)
 Since bind variables in oracle have no special characters, this setString method differs from the common one in that it does not single quote strings.
 setTimestamp ($paramIndex, $value)
 Copied this function from common/PreparedStatement.php and modified to work with Oracle Please note the format used with date() matches that of NLS_DATE_FORMAT set in OCI8Connection.php.
 setDate ($paramIndex, $value)
 Please note the format used with date() matches that of NLS_DATE_FORMAT set in OCI8Connection.php.
 setNull ($paramIndex)

Protected Member Functions

 escape ($str)
 Nothing to do - since oci_bind is used to insert data, no escaping is needed.

Private Member Functions

 bindVars ($stmt)
 Performs the actual binding of variables using oci_bind_by_name().
 sqlToOracleBindVars ($sql)
 Convert a Propel SQL into Oracle SQL.
 setColumnArray ()
 In order to send lob data (clob/blob) to the Oracle data base, the sqlToOracleBindVars function needs to have an ordered list of the columns being addressed in the sql statement.

Private Attributes

 $lobDescriptors = array()
 $lobs = array()
 $columns = array()


Detailed Description

Definition at line 33 of file OCI8PreparedStatement.php.


Member Function Documentation

OCI8PreparedStatement::bindVars ( stmt  )  [private]

Performs the actual binding of variables using oci_bind_by_name().

This may seem like useless overhead, but the reason why calls to oci_bind_by_name() are not performed in the set*() methods is that it is possible that the SQL will need to be modified -- e.g. by a setLimit() call -- and re-prepared. We cannot assume that the statement has been prepared when the set*() calls are invoked. This also means, therefore, that the set*() calls will not throw exceptions; all exceptions will be thrown when the statement is prepared.

Parameters:
resource $stmt The statement result of oci_parse to use for binding.
Returns:
void

Definition at line 197 of file OCI8PreparedStatement.php.

Referenced by executeQuery(), and executeUpdate().

00198     {
00199         foreach ($this->boundInVars as $idx => $val) {
00200             $idxName = ":var" . $idx;
00201             if (!oci_bind_by_name($stmt, $idxName, $this->boundInVars[$idx], -1)) {
00202                 throw new SQLException("Erorr binding value to placeholder " . $idx);
00203             } 
00204         } // foreach
00205 
00206         foreach ($this->lobs as $idx => $val) {
00207             $idxName = ":var" . $idx;
00208             if (class_exists('Blob') && $val instanceof Blob){
00209                 if (!oci_bind_by_name($stmt, $idxName, $this->lobDescriptors[$idx], -1, OCI_B_BLOB))
00210                     throw new SQLException("Erorr binding blob to placeholder " . $idx);
00211             } elseif (class_exists('Clob') && $val instanceof Clob){
00212                 if (!oci_bind_by_name($stmt, $idxName, $this->lobDescriptors[$idx], -1, OCI_B_CLOB))
00213                     throw new SQLException("Erorr binding clob to placeholder " . $idx);
00214             }
00215         } // foreach
00216     }

OCI8PreparedStatement::close (  ) 

If the statement is set, free it.

See also:
PreparedStatement::close()

Reimplemented from PreparedStatementCommon.

Definition at line 62 of file OCI8PreparedStatement.php.

00063     {
00064          if (isset($this->stmt))
00065               @oci_free_statement($this->stmt);
00066     }

OCI8PreparedStatement::escape ( str  )  [protected]

Nothing to do - since oci_bind is used to insert data, no escaping is needed.

Parameters:
string $str
Returns:
string

Reimplemented from PreparedStatementCommon.

Definition at line 73 of file OCI8PreparedStatement.php.

00074     {
00075         return $str;
00076     }

OCI8PreparedStatement::executeQuery ( p1 = null,
fetchmode = null 
)

Executes the SQL query in this PreparedStatement object and returns the resultset generated by the query.

Parameters:
mixed $p1 Either (array) Parameters that will be set using PreparedStatement::set() before query is executed or (int) fetchmode.
int $fetchmode The mode to use when fetching the results (e.g. ResultSet::FETCHMODE_NUM, ResultSet::FETCHMODE_ASSOC).
Returns:
ResultSet
Exceptions:
SQLException if a database access error occurs.

Reimplemented from PreparedStatementCommon.

Definition at line 85 of file OCI8PreparedStatement.php.

References $result, PreparedStatementCommon::$sql, bindVars(), and sqlToOracleBindVars().

00086     {
00087         $params = null;
00088         if ($fetchmode !== null) {
00089             $params = $p1;
00090         } elseif ($p1 !== null) {
00091             if (is_array($p1)) $params = $p1;
00092             else $fetchmode = $p1;
00093         }
00094         
00095         if ($params) {
00096             for($i=0,$cnt=count($params); $i < $cnt; $i++) {
00097                 $this->set($i+1, $params[$i]);
00098             }
00099         }
00100 
00101         $this->updateCount = null; // reset        
00102                 
00103         $sql = $this->sqlToOracleBindVars($this->sql);
00104         
00105         if ($this->limit > 0 || $this->offset > 0) {
00106             $this->conn->applyLimit($sql, $this->offset, $this->limit);
00107         }
00108         
00109         $result = oci_parse($this->conn->getResource(), $sql);
00110         if (!$result) {
00111             throw new SQLException("Unable to prepare query", $this->conn->nativeError(), $this->sqlToOracleBindVars($this->sql));
00112         }
00113         
00114         // bind all variables
00115         $this->bindVars($result);
00116         
00117         $success = oci_execute($result, OCI_DEFAULT);
00118         if (!$success) {
00119             throw new SQLException("Unable to execute query", $this->conn->nativeError($result), $this->sqlToOracleBindVars($this->sql));
00120         }
00121         
00122         $this->resultSet = new OCI8ResultSet($this->conn, $result, $fetchmode);
00123         
00124         return $this->resultSet;
00125     }

OCI8PreparedStatement::executeUpdate ( params = null  ) 

Executes the SQL INSERT, UPDATE, or DELETE statement in this PreparedStatement object.

Parameters:
array $params Parameters that will be set using PreparedStatement::set() before query is executed.
Returns:
int Number of affected rows (or 0 for drivers that return nothing).
Exceptions:
SQLException if a database access error occurs.

Reimplemented from PreparedStatementCommon.

Definition at line 134 of file OCI8PreparedStatement.php.

References bindVars(), and sqlToOracleBindVars().

00135     {
00136         if ($params) {
00137             for($i=0,$cnt=count($params); $i < $cnt; $i++) {
00138                 $this->set($i+1, $params[$i]);
00139             }
00140         }
00141 
00142         if($this->resultSet) $this->resultSet->close();
00143         $this->resultSet = null; // reset
00144 
00145         $stmt = oci_parse($this->conn->getResource(), $this->sqlToOracleBindVars($this->sql));
00146 
00147         if (!$stmt) {
00148             throw new SQLException("Unable to prepare update", $this->conn->nativeError(), $this->sqlToOracleBindVars($this->sql));
00149         }
00150         
00151         // bind all variables
00152         $this->bindVars($stmt); 
00153 
00154         // Even if autocommit is on, delay commit until after LOBS have been saved
00155         $success = oci_execute($stmt, OCI_DEFAULT);
00156         if (!$success) {
00157             throw new SQLException("Unable to execute update", $this->conn->nativeError($stmt), $this->sqlToOracleBindVars($this->sql));
00158         }        
00159 
00160         // save data in any LOB descriptors, then free them
00161         foreach($this->lobDescriptors as $paramIndex => $lobster) {
00162             $lob = $this->lobs[$paramIndex]; // corresponding Blob/Clob
00163             if ($lob->isFromFile()) {
00164                 $success = $lobster->savefile($lob->getInputFile());
00165             } else {
00166                 $success = $lobster->save($lob->getContents());
00167             }
00168             if (!$success) {                
00169                 $lobster->free();
00170                 throw new SQLException("Error saving lob bound to " . $paramIndex);
00171             }
00172             $lobster->free();
00173         }
00174 
00175         if ($this->conn->getAutoCommit()) {
00176             oci_commit($this->conn->getResource()); // perform deferred commit
00177         }
00178         
00179         $this->updateCount = @oci_num_rows($stmt);
00180 
00181         return $this->updateCount;
00182     }

OCI8PreparedStatement::setBlob ( paramIndex,
blob 
)

Parameters:
string $paramIndex
mixed $blob Blob object or string containing data.
Returns:
void

Reimplemented from PreparedStatementCommon.

Definition at line 280 of file OCI8PreparedStatement.php.

00281     {
00282         require_once 'creole/util/Blob.php';
00283         if (!($blob instanceof Blob)) {
00284             $b = new Blob();
00285             $b->setContents($blob);
00286             $blob = $b;
00287         }
00288         $this->lobDescriptors[$paramIndex] = oci_new_descriptor($this->conn->getResource(), OCI_D_LOB);
00289         $this->lobs[$paramIndex] = $blob;        
00290     }

OCI8PreparedStatement::setClob ( paramIndex,
clob 
)

Parameters:
string $paramIndex
mixed $clob Clob object or string containing data.
Returns:
void

Reimplemented from PreparedStatementCommon.

Definition at line 297 of file OCI8PreparedStatement.php.

00298     {
00299         require_once 'creole/util/Clob.php';
00300         if (!($clob instanceof Clob)) {
00301             $c = new Clob();
00302             $c->setContents($clob);
00303             $clob = $c;
00304         }
00305         $this->lobDescriptors[$paramIndex] = oci_new_descriptor($this->conn->getResource(), OCI_D_LOB);
00306         $this->lobs[$paramIndex] = $clob;        
00307     }

OCI8PreparedStatement::setColumnArray (  )  [private]

In order to send lob data (clob/blob) to the Oracle data base, the sqlToOracleBindVars function needs to have an ordered list of the columns being addressed in the sql statement.

Since only insert and update statements require special handling, there are two ways to find the columns: 1) find the first set of () and parse out the columns names based on the token ',' 2) find all the text strings to the left of the equal signs.

Parameters:
void 
Returns:
void

Definition at line 384 of file OCI8PreparedStatement.php.

Referenced by sqlToOracleBindVars().

00385     {
00386         $this->columns = array();
00387 
00388         //handle the simple insert case first
00389         if(strtoupper(substr($this->sql, 0, 6)) == 'INSERT') {
00390             $firstPos = strpos($this->sql, '(');
00391             $secPos = strpos($this->sql, ')');
00392             $collist = substr($this->sql, $firstPos + 1, $secPos - $firstPos - 1);
00393             $this->columns = explode(',', $collist);
00394         }
00395         if (strtoupper(substr($this->sql, 0, 6)) == 'UPDATE') {
00396             //handle more complex update case
00397             //first get the string setup so we can explode based on '=?'
00398             //second split results from previous action based on ' '
00399             // the last token from this should be a column name
00400             $tmp = $this->sql;
00401             $tmp = str_replace(" =", "=", $this->sql);
00402             $tmp = str_replace("= ", "=", $tmp);
00403             $tmp = str_replace(",", " ", $tmp);
00404             $stage1 = explode("=?",$tmp);
00405             
00406             foreach($stage1 as $chunk) {
00407                 $stage2 = explode(' ', $chunk);
00408                 $this->columns[count($this->columns)] = $stage2[count($stage2) - 1];
00409             }
00410         }
00411    }

OCI8PreparedStatement::setDate ( paramIndex,
value 
)

Please note the format used with date() matches that of NLS_DATE_FORMAT set in OCI8Connection.php.

Parameters:
int $paramIndex
string $value
Returns:
void

Reimplemented from PreparedStatementCommon.

Definition at line 360 of file OCI8PreparedStatement.php.

References setNull().

00361     {
00362         if ($value === null) {
00363             $this->setNull($paramIndex);
00364         } else {
00365             if (is_numeric($value)) $value = date("Y-m-d", $value);
00366             elseif (is_object($value)) $value = date("Y-m-d", $value->getTime());
00367             $this->boundInVars[$paramIndex] = $value;
00368         }
00369     }

OCI8PreparedStatement::setNull ( paramIndex  ) 

Parameters:
int $paramIndex
Returns:
void

Reimplemented from PreparedStatementCommon.

Definition at line 417 of file OCI8PreparedStatement.php.

Referenced by setDate(), setString(), and setTimestamp().

00418     {
00419         $this->boundInVars[$paramIndex] = '';
00420     }

OCI8PreparedStatement::setString ( paramIndex,
value 
)

Since bind variables in oracle have no special characters, this setString method differs from the common one in that it does not single quote strings.

Parameters:
int $paramIndex
string $value
Returns:
void

Reimplemented from PreparedStatementCommon.

Definition at line 317 of file OCI8PreparedStatement.php.

References setNull().

00318     {
00319         if ($value === null) {
00320             $this->setNull($paramIndex);
00321         } else {
00322             // it's ok to have a fatal error here, IMO, if object doesn't have
00323             // __toString() and is being passed to this method.
00324             if ( is_object ( $value ) ) {
00325                 $this->boundInVars[$paramIndex] = $value->__toString();
00326             } else {
00327                 $this->boundInVars[$paramIndex] = (string)$value;
00328             }
00329         }
00330     }

OCI8PreparedStatement::setTimestamp ( paramIndex,
value 
)

Copied this function from common/PreparedStatement.php and modified to work with Oracle Please note the format used with date() matches that of NLS_DATE_FORMAT set in OCI8Connection.php.

Parameters:
int $paramIndex
string $value
Returns:
void

Reimplemented from PreparedStatementCommon.

Definition at line 341 of file OCI8PreparedStatement.php.

References setNull().

00342     {
00343         if ($value === null) {
00344             $this->setNull($paramIndex);
00345         } else {
00346             if (is_numeric($value)) $value = date('Y-m-d H:i:s', $value);
00347             elseif (is_object($value)) $value = date('Y-m-d H:i:s', $value->getTime());
00348             $this->boundInVars[$paramIndex] = $value;
00349         }
00350     }

OCI8PreparedStatement::sqlToOracleBindVars ( sql  )  [private]

Convert a Propel SQL into Oracle SQL.

Look for all of the '?' and replace with ":varX"

Parameters:
string $sql SQL in Propel native format
Returns:
string SQL in Oracle Bind Var format
Todo:
-cOCI8PreparedStatement Consider changing this implementation to use the fact that we already know where all the '?' chars are (in $positions array).

Definition at line 229 of file OCI8PreparedStatement.php.

References PreparedStatementCommon::$sql, and setColumnArray().

Referenced by executeQuery(), and executeUpdate().

00230     {
00231         $out = "";
00232         $in_literal = 0;
00233         $idxNum = 1;
00234         for ($i = 0; $i < strlen($sql); $i++) {
00235             $char = $sql[$i];
00236             if (strcmp($char,"'")==0) {
00237                 $in_literal = ~$in_literal;
00238             }
00239             if (strcmp($char,"?")==0 && !$in_literal) {
00240                 if (array_key_exists($idxNum, $this->lobs)){
00241                     if (class_exists('Blob') && ($this->lobs[$idxNum] instanceof Blob))
00242                         $out .= "empty_blob()";
00243                     if (class_exists('Clob') && ($this->lobs[$idxNum] instanceof Clob))
00244                         $out .= "empty_clob()";
00245                 } else
00246                     $out .= ":var" . $idxNum;
00247                 $idxNum++;
00248             } else {
00249                 $out .= $char;
00250             }
00251         }
00252 
00253         if (isset($this->lobs) && !empty($this->lobs)) {
00254             $this->setColumnArray();
00255 
00256             $retstmt = " Returning ";
00257             $collist = "";
00258             $bindlist = "";
00259             foreach ($this->lobs as $idx=>$val) {
00260                 $idxName = ":var" . $idx;
00261                 if ((class_exists('Blob') && $val instanceof Blob) || (class_exists('Clob') && $val instanceof Clob)) {
00262                     //the columns array starts at zero instead of 1 like the lobs array
00263                     $collist .= $this->columns[$idx-1] . ",";
00264                     $bindlist .= $idxName . ",";
00265                 }
00266             }
00267 
00268             if (!empty($collist))
00269                 $out .= $retstmt . rtrim($collist, ",") . " into " . rtrim($bindlist, ",");
00270         }
00271 
00272         return $out;
00273     }


Member Data Documentation

OCI8PreparedStatement::$columns = array() [private]

Definition at line 56 of file OCI8PreparedStatement.php.

OCI8PreparedStatement::$lobDescriptors = array() [private]

Definition at line 42 of file OCI8PreparedStatement.php.

OCI8PreparedStatement::$lobs = array() [private]

Definition at line 49 of file OCI8PreparedStatement.php.


The documentation for this class was generated from the following file:

Generated on Wed May 6 23:10:50 2009 for fareofficelib by  doxygen 1.5.8