Oracle.php

浏览该文件的文档。
00001 <?php
00003 // FleaPHP Framework
00004 //
00005 // 该文件由“夜猫子”共享,特此感谢!
00007 
00019 // {{{ includes
00020 FLEA::loadClass('FLEA_Db_Driver_Abstract');
00021 // }}}
00022 
00030 class FLEA_Db_Driver_Oracle extends FLEA_Db_Driver_Abstract
00031 {
00032     var $NEXT_ID_SQL    = "SELECT (%s.nextval) FROM DUAL";
00033     var $CREATE_SEQ_SQL = "CREATE SEQUENCE %s START WITH %s";
00034     var $DROP_SEQ_SQL   = "DROP SEQUENCE %s";
00035     var $META_COLUMNS_SQL = "SELECT CNAME, COLTYPE, WIDTH, SCALE, PRECISION, NULLS, DEFAULTVAL FROM COL WHERE TNAME=%s ORDER BY COLNO";
00036     var $PARAM_STYLE = DBO_PARAM_CL_NAMED;
00037     var $HAS_AFFECTED_ROWS = true;
00038     var $HAS_TRANSACTION = true;
00039     var $HAS_SAVEPOINT = true;
00040     var $RESULT_FIELD_NAME_LOWER = true;
00041     var $NLS_DATE_FORMAT = 'yyyy-mm-dd hh24:mi:ss';
00042 
00046     var $_lastrs = null;
00047 
00051     var $_commitMode = OCI_COMMIT_ON_SUCCESS;
00052 
00053     function connect($dsn = false)
00054     {
00055         $this->lasterr = null;
00056         $this->lasterrcode = null;
00057 
00058         if ($this->conn && $dsn == false) { return true; }
00059         if (!$dsn) {
00060             $dsn = $this->dsn;
00061         } else {
00062             $this->dsn = $dsn;
00063         }
00064         if (isset($dsn['charset']) && $dsn['charset'] != '') {
00065             $charset = $dsn['charset'];
00066         } else {
00067             $charset = FLEA::getAppInf('databaseCharset');
00068         }
00069         if (strtoupper($charset) == 'GB2312') { $charset = 'GBK'; }
00070         if (empty($dsn['database'])) {
00071             $dsn['database'] = null;
00072         }
00073         if ($charset != '') {
00074             $this->conn = ocilogon("{$dsn['login']}", $dsn['password'], $dsn['database'], $charset);
00075         } else {
00076             $this->conn = ocilogon($dsn['login'], $dsn['password'], $dsn['database']);
00077         }
00078 
00079         if (!$this->conn) {
00080             FLEA::loadClass('FLEA_Db_Exception_SqlQuery');
00081             $err = ocierror();
00082             __THROW(new FLEA_Db_Exception_SqlQuery("ocilogon('{$dsn['login']}') failed.", $err['message'], $err['code']));
00083             return false;
00084         }
00085         
00086         $this->execute("ALTER SESSION SET NLS_DATE_FORMAT = '{$this->NLS_DATE_FORMAT}'");
00087 
00088         return true;
00089     }
00090 
00091     function selectDb($database)
00092     {
00093         $this->execute("ALTER SESSION CURRENT_SCHEMA = {$database}");
00094     }
00095 
00096     function close()
00097     {
00098         if ($this->conn) { ocilogoff($this->conn); }
00099         parent::close();
00100     }
00101 
00102     function execute($sql, $inputarr = null, $throw = true)
00103     {
00104         if ($this->enableLog) {
00105             $this->log[] = $sql;
00106             log_message("sql: {$sql}", 'debug');
00107         }
00108 
00109         $this->querycount++;
00110         $stmt = ociparse($this->conn, $sql);
00111 
00112         if (is_array($inputarr)) {
00113             foreach (array_keys($inputarr) as $k) {
00114                 ocibindbyname($stmt, $k, $inputarr[$k], -1);
00115             }
00116         }
00117 
00118         if ($stmt && ociexecute($stmt, $this->_commitMode)) {
00119             $this->_lastrs = $stmt;
00120             $this->lasterr = null;
00121             $this->lasterrcode = null;
00122             return $stmt;
00123         }
00124 
00125         $err = ocierror($stmt);
00126         $this->lasterr = $err['message'];
00127         $this->lasterrcode = $err['code'];
00128 
00129         if ($throw) {
00130             FLEA::loadClass('FLEA_Db_Exception_SqlQuery');
00131             __THROW(new FLEA_Db_Exception_SqlQuery($sql, $this->lasterr, $this->lasterrcode));
00132         }
00133         return false;
00134     }
00135 
00136     function qstr($value)
00137     {
00138         if (is_int($value) || is_float($value)) { return $value; }
00139         if (is_bool($value)) { return $value ? $this->TRUE_VALUE : $this->FALSE_VALUE; }
00140         if (is_null($value)) { return $this->NULL_VALUE; }
00141         $value = str_replace("'", "''", $value);
00142         return  "'" . addcslashes($value, "\000\n\r\\\032") . "'";
00143     }
00144 
00145     function qtable($tableName, $schema = null)
00146     {
00147         return $schema != '' ? "{$schema}.{$tableName}" : $tableName;
00148     }
00149 
00150     function qfield($fieldName, $tableName = null, $schema = null)
00151     {
00152         return $tableName != '' ? $this->qtable($tableName, $schema) . '.' . $fieldName : $fieldName;
00153     }
00154 
00155     function _affectedRows()
00156     {
00157         return is_resource($this->_lastrs) ? ocirowcount($this->_lastrs) : false;
00158     }
00159 
00160     function & fetchRow($stmt)
00161     {
00162         $row = array();
00163         ocifetchinto($stmt, $row, OCI_NUM | OCI_RETURN_LOBS);
00164         return $row;
00165     }
00166 
00167     function & fetchAssoc($stmt)
00168     {
00169         $row = array();
00170         ocifetchinto($stmt, $row, OCI_ASSOC | OCI_RETURN_LOBS);
00171         if ($this->RESULT_FIELD_NAME_LOWER) {
00172             $row = array_change_key_case($row, CASE_LOWER);
00173         }
00174         return $row;
00175     }
00176 
00177     function freeRes($stmt)
00178     {
00179         ocifreestatement($stmt);
00180     }
00181 
00185     function selectLimit($sql, $length = 'ALL', $offset = 0)
00186     {
00187         if (strpos($sql, '/*+') !== false) {
00188             $sql = str_replace('/*+ ', '/*+FIRST_ROWS ', $sql);
00189         } else {
00190             $sql = preg_replace('/^[ \t\n]*SELECT/i', 'SELECT /*+FIRST_ROWS*/', $sql);
00191         }
00192 
00193         $selectOffsetAlg1 = 100;
00194         $inputarr = array();
00195         if ($offset < $selectOffsetAlg1) {
00196             if ($length > 0) {
00197                 if ($offset > 0) { $length += $offset; }
00198                 $sql = "SELECT * FROM ({$sql}) WHERE ROWNUM <= :length";
00199                 $inputarr['length'] = $length;
00200             }
00201             $stmt = $this->execute($sql, $inputarr);
00202             for ($i = 0; $i < $offset; $i++) {
00203                 ocifetch($stmt);
00204             }
00205             return $stmt;
00206         } else {
00207              // Algorithm by Tomas V V Cox, from PEAR DB oci8.php
00208 
00209              // Let Oracle return the name of the columns
00210             $qfields = "SELECT * FROM ({$sql}) WHERE NULL = NULL";
00211             $stmt = ociparse($this->conn, $qfields);
00212             if (!$stmt) { return false; }
00213 
00214             if (is_array($inputarr)) {
00215                 foreach (array_keys($inputarr) as $k) {
00216                     ocibindbyname($stmt, $k, $inputarr[$k], -1);
00217                 }
00218             }
00219 
00220             if (!ociexecute($stmt, OCI_DEFAULT)) {
00221                 ocifreestatement($stmt);
00222                 return false;
00223             }
00224 
00225             $ncols = ocinumcols($stmt);
00226             for ($i = 1; $i <= $ncols; $i++) {
00227                 $cols[] = '"' . ocicolumnname($stmt, $i) . '"';
00228             }
00229 
00230             ocifreestatement($stmt);
00231             $fields = implode(', ', $cols);
00232             $length += $offset;
00233             $offset += 1; // in Oracle rownum starts at 1
00234 
00235             $sql = "SELECT {$fields} FROM " .
00236                    "(SELECT rownum as adodb_rownum, {$fields} FROM " .
00237                    "({$sql})" .
00238                    ' WHERE rownum <= :adodb_nrows) WHERE adodb_rownum >= :adodb_offset';
00239             $inputarr['adodb_nrows'] = $length;
00240             $inputarr['adodb_offset'] = $offset;
00241 
00242             return $this->execute($sql, $inputarr);
00243         }
00244     }
00245 
00246     function & metaColumns($table, $normalize = true)
00247     {
00248         static $typeMap = array(
00249             'VARCHAR' => 'C',
00250             'VARCHAR2' => 'C',
00251             'CHAR' => 'C',
00252             'VARBINARY' => 'C',
00253             'BINARY' => 'C',
00254             'NCHAR' => 'C',
00255             'NVARCHAR' => 'C',
00256             'NVARCHAR2' => 'C',
00257 
00258             'NCLOB' => 'X',
00259             'LONG' => 'X',
00260             'LONG VARCHAR' => 'X',
00261             'CLOB' => 'X',
00262 
00263             'LONG RAW' => 'B',
00264             'LONG VARBINARY' => 'B',
00265             'BLOB' => 'B',
00266 
00267             'DATE' => 'D',
00268 
00269 
00270             'TIMESTAMP' => 'T',
00271 
00272             'INT' => 'I',
00273             'SMALLINT' => 'I',
00274             'INTEGER' => 'I',
00275         );
00276 
00277         $arr = explode('.', $table);
00278         $table = $this->qstr(strtoupper($arr[count($arr) - 1]));
00279         $stmt = $this->execute(sprintf($this->META_COLUMNS_SQL, $table));
00280         if (!$stmt) { return false; }
00281 
00282         $retarr = array();
00283         $row = array();
00284         while (ocifetchinto($stmt, $row, OCI_NUM)) {
00285             $field = array();
00286             if ($this->RESULT_FIELD_NAME_LOWER) {
00287                 $field['name'] = strtolower($row[0]);
00288             } else {
00289                 $field['name'] = $row[0];
00290             }
00291             $field['type'] = preg_replace('/\([0-9]+\)/', '', $row[1]);
00292             $field['maxLength'] = $row[2];
00293             $field['scale'] = isset($row[3]) ? $row[3] : null;
00294             if ($field['type'] == 'NUMBER') {
00295                 if ($field['scale'] == 0) { $field['type'] = 'INT'; }
00296                 $field['maxLength'] = isset($row[4]) ? $row[4] : null;
00297             }
00298             $field['notNull'] = (strncmp($row[5], 'NOT',3) === 0);
00299             $field['binary'] = (strpos($field['type'], 'BLOB') !== false);
00300             $field['hasDefault'] = isset($row[6]);
00301             $field['defaultValue'] = isset($row[6]) ? $row[6] : null;
00302 
00303             $t = strtoupper($field['type']);
00304             if (isset($typeMap[$t])) {
00305                 $field['simpleType'] = $typeMap[$t];
00306             } else {
00307                 $field['simpleType'] = 'N';
00308             }
00309             $field['autoIncrement'] = false;
00310             $field['primaryKey'] = false;
00311 
00312             if ($normalize) {
00313                 $retarr[strtoupper($field['name'])] = $field;
00314             } else {
00315                 $retarr[$field['name']] = $field;
00316             }
00317         }
00318         ocifreestatement($stmt);
00319 
00320         // 确定主键字段
00321         $ptab = 'USER_';
00322         $sql = "SELECT /*+ RULE */ distinct b.column_name FROM {$ptab}CONSTRAINTS a, {$ptab}CONS_COLUMNS b WHERE ( UPPER(b.table_name) = ({$table}))  AND (UPPER(a.table_name) = ({$table}) and a.constraint_type = 'P') AND (a.constraint_name = b.constraint_name)";
00323         $stmt = $this->execute($sql);
00324         if ($stmt) {
00325             $row = array();
00326             while (ocifetchinto($stmt, $row, OCI_NUM)) {
00327                 $pkname = strtoupper($row[0]);
00328                 if (isset($retarr[$pkname])) {
00329                     $retarr[$pkname]['primaryKey'] = true;
00330                     if ($retarr[$pkname]['type'] == 'INT') {
00331                         $retarr[$pkname]['simpleType'] = 'R';
00332                     }
00333                 }
00334             }
00335             ocifreestatement($stmt);
00336         }
00337 
00338         return $retarr;
00339     }
00340 
00341     function dbTimeStamp($timestamp)
00342     {
00343         if (empty($timestamp) && $timestamp !== 0) { return 'null'; }
00344         return date('Y-m-d h:i:s', $timestamp);
00345     }
00346 
00347     function _startTrans()
00348     {
00349         $this->_commitMode = OCI_DEFAULT;
00350     }
00351 
00352     function _completeTrans($commitOnNoErrors = true)
00353     {
00354         if ($this->_hasFailedQuery == false && $commitOnNoErrors) {
00355             $this->execute('COMMIT');
00356         } else {
00357             $this->execute('ROLLBACK');
00358         }
00359         $this->_commitMode = OCI_COMMIT_ON_SUCCESS;
00360     }
00361 }

Generated at Sat Feb 2 15:18:51 2008 for FleaPHP by  doxygen 1.5.3