00001 <?php
00003
00004
00005
00007
00019
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, '
00188
00189
00190 ', $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
00208
00209
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;
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 }