00001 <?php
00002
00023 require_once 'creole/Connection.php';
00024 require_once 'creole/common/ConnectionCommon.php';
00025 include_once 'creole/drivers/oracle/OCI8ResultSet.php';
00026
00037 class OCI8Connection extends ConnectionCommon implements Connection
00038 {
00039 protected $lastStmt = null;
00040
00045 protected $execMode = OCI_COMMIT_ON_SUCCESS;
00046
00056 function connect( $dsninfo, $flags = 0 )
00057 {
00058 if ( !extension_loaded( 'oci8' ) )
00059 {
00060 throw new SQLException( 'oci8 extension not loaded' );
00061 }
00062
00063 $this->dsn = $dsninfo;
00064 $this->flags = $flags;
00065
00066 $persistent =
00067 ( $flags & Creole::PERSISTENT === Creole::PERSISTENT );
00068
00069 $user = $dsninfo[ 'username' ];
00070 $pw = $dsninfo[ 'password' ];
00071 $hostspec = $dsninfo[ 'hostspec' ];
00072 $db = $dsninfo[ 'database' ];
00073
00074 $connect_function = ( $persistent )
00075 ? 'oci_pconnect'
00076 : 'oci_connect';
00077
00078 $encoding = !empty($dsninfo['encoding']) ? $dsninfo['encoding'] : null;
00079
00080 @ini_set( 'track_errors', true );
00081
00082 if ( $db && $hostspec && $user && $pw )
00083 {
00084 $conn = @$connect_function( $user, $pw, "//$hostspec/$db", $encoding);
00085 }
00086 elseif ( $hostspec && $user && $pw )
00087 {
00088 $conn = @$connect_function( $user, $pw, $hostspec, $encoding );
00089 }
00090
00091 elseif ( $user || $pw )
00092 {
00093 $conn = @$connect_function( $user, $pw, null, $encoding );
00094 }
00095
00096 else
00097 {
00098 $conn = false;
00099 }
00100
00101 @ini_restore( 'track_errors' );
00102
00103 if ( $conn == false )
00104 {
00105 $error = oci_error();
00106 $error = ( is_array( $error ) )
00107 ? $error[ 'message' ]
00108 : null;
00109
00110 throw new SQLException( 'connect failed', $error );
00111 }
00112
00113 $this->dblink = $conn;
00114
00115
00116
00117
00118 $sql = "ALTER SESSION SET NLS_DATE_FORMAT='YYYY-MM-DD HH24:MI:SS'";
00119 $this->executeQuery($sql);
00120 }
00121
00122
00126 function close()
00127 {
00128 $ret = @oci_close( $this->dblink );
00129 $this->dblink = null;
00130 return $ret;
00131 }
00132
00136 function executeQuery( $sql, $fetchmode = null )
00137 {
00138 $this->lastQuery = $sql;
00139
00140
00141 $result = oci_parse( $this->dblink, $sql );
00142
00143 if ( ! $result )
00144 {
00145 throw new SQLException( 'Unable to prepare query'
00146 , $this->nativeError()
00147 , $sql
00148 );
00149 }
00150
00151 $success = oci_execute( $result, $this->execMode );
00152
00153 if ( ! $success )
00154 {
00155 throw new SQLException( 'Unable to execute query'
00156 , $this->nativeError( $result )
00157 , $sql
00158 );
00159 }
00160
00161 return new OCI8ResultSet( $this, $result, $fetchmode );
00162 }
00163
00164
00169 function executeUpdate( $sql )
00170 {
00171 $this->lastQuery = $sql;
00172
00173 $statement = oci_parse( $this->dblink, $sql );
00174
00175 if ( ! $statement )
00176 {
00177 throw new SQLException( 'Unable to prepare update'
00178 , $this->nativeError()
00179 , $sql
00180 );
00181 }
00182
00183 $success = oci_execute( $statement, $this->execMode );
00184
00185 if ( ! $success )
00186 {
00187 throw new SQLException( 'Unable to execute update'
00188 , $this->nativeError( $statement )
00189 , $sql
00190 );
00191 }
00192
00193 $this->lastStmt = $statement;
00194
00195 return oci_num_rows( $statement );
00196 }
00197
00203 protected function beginTrans()
00204 {
00205 $this->execMode = OCI_DEFAULT;
00206 }
00207
00213 protected function commitTrans()
00214 {
00215 $result = oci_commit( $this->dblink );
00216
00217 if ( ! $result )
00218 {
00219 throw new SQLException( 'Unable to commit transaction'
00220 , $this->nativeError()
00221 );
00222 }
00223
00224 $this->execMode = OCI_COMMIT_ON_SUCCESS;
00225 }
00226
00227
00233 protected function rollbackTrans()
00234 {
00235 $result = oci_rollback( $this->dblink );
00236
00237 if ( ! $result )
00238 {
00239 throw new SQLException( 'Unable to rollback transaction'
00240 , $this->nativeError()
00241 );
00242 }
00243
00244 $this->execMode = OCI_COMMIT_ON_SUCCESS;
00245 }
00246
00247
00255 function getUpdateCount()
00256 {
00257 if ( ! $this->lastStmt )
00258 {
00259 return 0;
00260 }
00261
00262 $result = oci_num_rows( $this->lastStmt );
00263
00264 if ( $result === false )
00265 {
00266 throw new SQLException( 'Update count failed'
00267 , $this->nativeError( $this->lastStmt )
00268 );
00269 }
00270
00271 return $result;
00272 }
00273
00274
00293 public function applyLimit( &$sql, $offset, $limit )
00294 {
00295 $sql =
00296 'SELECT B.* FROM ( '
00297 . 'SELECT A.*, rownum AS CREOLE$ROWNUM FROM ( '
00298 . $sql
00299 . ' ) A '
00300 . ' ) B WHERE ';
00301
00302 if ( $offset > 0 )
00303 {
00304 $sql .= ' B.CREOLE$ROWNUM > ' . $offset;
00305
00306 if ( $limit > 0 )
00307 {
00308 $sql .= ' AND B.CREOLE$ROWNUM <= '
00309 . ( $offset + $limit );
00310 }
00311 }
00312
00313 else
00314 {
00315 $sql .= ' B.CREOLE$ROWNUM <= ' . $limit;
00316 }
00317 }
00318
00325 public function nativeError( $result = null )
00326 {
00327 if ( $result !== null )
00328 {
00329 $error = oci_error( $result );
00330 }
00331
00332 else
00333 {
00334 $error = oci_error( $this->dblink );
00335 }
00336
00337 return $error[ 'code' ] . ': ' . $error[ 'message' ];
00338 }
00339
00340
00344 public function getDatabaseInfo()
00345 {
00346 require_once 'creole/drivers/oracle/metadata/OCI8DatabaseInfo.php';
00347
00348 return new OCI8DatabaseInfo( $this );
00349 }
00350
00354 public function getIdGenerator()
00355 {
00356 require_once 'creole/drivers/oracle/OCI8IdGenerator.php';
00357
00358 return new OCI8IdGenerator( $this );
00359 }
00360
00369 public function prepareStatement( $sql )
00370 {
00371 require_once 'creole/drivers/oracle/OCI8PreparedStatement.php';
00372
00373 return new OCI8PreparedStatement( $this, $sql );
00374 }
00375
00379 public function prepareCall( $sql )
00380 {
00381 throw new SQLException( 'Oracle driver does not yet support stored procedures using CallableStatement.' );
00382 }
00383
00387 public function createStatement()
00388 {
00389 require_once 'creole/drivers/oracle/OCI8Statement.php';
00390
00391 return new OCI8Statement( $this );
00392 }
00393 }