Sqlite.php

浏览该文件的文档。
00001 <?php
00002 
00014 class FLEA_Db_Driver_Sqlite
00015 {
00019     var $NEXT_ID_SQL    = "UPDATE %s SET id = LAST_INSERT_ID(id + 1)";
00020     var $CREATE_SEQ_SQL = "CREATE TABLE %s (id INT NOT NULL)";
00021     var $INIT_SEQ_SQL   = "INSERT INTO %s VALUES (%s)";
00022     var $DROP_SEQ_SQL   = "DROP TABLE %s";
00023 
00027     var $TRUE_VALUE  = 1;
00028     var $FALSE_VALUE = 0;
00029     var $NULL_VALUE = 'NULL';
00030 
00034     var $META_COLUMNS_SQL = "SELECT sql FROM sqlite_master WHERE type='table' and name='%s'";//sqlite 用这个表来保存数据库的SQL
00035 
00041     var $dsn = null;
00042 
00048     var $conn = null;
00049 
00055     var $log = array();
00056 
00062     var $enableLog = false;
00063 
00069     var $lasterr = null;
00070 
00076     var $lasterrcode = null;
00077 
00083     var $_insertId = null;
00084 
00090     var $_transCount = 0;
00091 
00097     var $_transCommit = true;
00098 
00104     function FLEA_Db_Driver_Sqlite($dsn = false)
00105     {
00106         $tmp = (array)$dsn;
00107         unset($tmp['password']);
00108         $this->dsn = $dsn;
00109         $this->enableLog = !defined('DEPLOY_MODE') || DEPLOY_MODE != true;
00110         if (!function_exists('log_message')) {
00111             $this->enableLog = false;
00112         }
00113     }
00114 
00122     function connect($dsn = false)
00123     {
00124         $dsn = $dsn? $dsn : $this->dsn;
00125         $this->conn=false;
00126         if(file_exists($dsn['db'])){
00127             $this->conn=sqlite_open($dsn['db']);
00128             if($this->conn){
00129                 return $this->conn;
00130             }
00131         }
00132         FLEA::loadClass('FLEA_Db_Exception_SqlQuery');
00133        __THROW(new FLEA_Db_Exception_SqlQuery("connect('{$dsn['db']}') failed!"));
00134         return false;
00135     }
00136 
00140     function close()
00141     {
00142         if ($this->conn) {
00143             sqlite_close($this->conn);
00144         }
00145         $this->conn = null;
00146         $this->lasterr = null;
00147         $this->lasterrcode = null;
00148         $this->_insertId = null;
00149         $this->_transCount = 0;
00150         $this->_transCommit = true;
00151     }
00152 
00162     function execute($sql, $inputarr = null, $throw = true)
00163     {
00164         if(substr($sql,0,11)=="INSERT INTO") {
00165             // 删除SQL中的指定的表,SQLITE不支持在插入中语句有表名在前面
00166             $len1 = strpos($sql, '(');
00167             $len2 = strpos($sql, ')');
00168             $len3 = strpos($sql,'VALUES');
00169             $temp = array();
00170             if($len2 < $len3){
00171                 $temp[]= substr($sql,0,$len1);
00172                 $temp[] = substr($sql,$len1,$len2-$len1);
00173                 $temp[] = substr($sql,$len2);
00174                 $temp[1] = eregi_replace("[a-z_0-9]+\\.", "", $temp[1]);
00175                 $sql = implode($temp);
00176             }
00177         }
00178         if (is_array($inputarr)) {
00179             $sql = $this->_prepareSql($sql, $inputarr);
00180         }
00181         if ($this->enableLog) {
00182             $this->log[] = $sql;
00183             log_message("sql:\n{$sql}", 'debug');
00184         }
00185 
00186         $result = @sqlite_query($sql, $this->conn);
00187         if ($result !== false) {
00188             $this->lasterr = null;
00189             $this->lasterrcode = null;
00190             return $result;
00191         }
00192         $this->lasterrcode = sqlite_last_error($this->conn);
00193         $this->lasterr = sqlite_error_string($this->lasterrcode);
00194         if (!$throw) { return false; }
00195 
00196         FLEA::loadClass('FLEA_Db_Exception_SqlQuery');
00197         __THROW(new FLEA_Db_Exception_SqlQuery($sql, $this->lasterr, $this->lasterrcode));
00198         return false;
00199     }
00200 
00208     function qstr($value)
00209     {
00210         if (is_bool($value)) { return $value ? $this->TRUE_VALUE : $this->FALSE_VALUE; }
00211         if (is_null($value)) { return $this->NULL_VALUE; }
00212         return "'" . sqlite_escape_string($value) . "'";
00213     }
00214 
00222     function qtable($tableName)
00223     {
00224         return $tableName;//SQLite 对转换支持不是很好,经常出错
00225     }
00226 
00235     function qfield($fieldName, $tableName = null)
00236     {
00237         $pos = strpos($fieldName, '.');
00238         if ($pos !== false) {
00239             $tableName = substr($fieldName, 0, $pos);
00240             $fieldName = substr($fieldName, $pos + 1);
00241         }
00242         if ($tableName != '') {
00243             if ($fieldName != '*') {
00244                 return "{$tableName}.{$fieldName}";
00245             } else {
00246                 return "{$tableName}.*";
00247             }
00248         } else {
00249             if ($fieldName != '*') {
00250                 return "{$fieldName}";
00251             } else {
00252                 return "*";
00253             }
00254         }
00255     }
00256 
00265     function qfields($fields, $tableName = null)
00266     {
00267         if (!is_array($fields)) {
00268             $fields = explode(',', $fields);
00269         }
00270         $return = array();
00271         foreach ($fields as $fieldName) {
00272             $fieldName = trim($fieldName);
00273             if ($fieldName == '') { continue; }
00274             $pos = strpos($fieldName, '.');
00275             if ($pos !== false) {
00276                 $tableName = substr($fieldName, 0, $pos);
00277                 $fieldName = substr($fieldName, $pos + 1);
00278             }
00279             if ($tableName != '') {
00280                 if ($fieldName != '*') {
00281                     $return[] = "{$tableName}.{$fieldName}";
00282                 } else {
00283                     $return[] = "{$tableName}.*";
00284                 }
00285             } else {
00286                 if ($fieldName != '*') {
00287                     $return[] = "{$fieldName}";
00288                 } else {
00289                     $return[] = '*';
00290                 }
00291             }
00292         }
00293         return implode(', ', $return);
00294     }
00295 
00304     function nextId($seqName = 'sdboseq', $startValue = 1)
00305     {
00306         $result = $this->execute(sprintf($this->NEXT_ID_SQL, $seqName), null, false);
00307         if ($result === false) {
00308             if (!$this->createSeq($seqName, $startValue)) { return false; }
00309             $this->execute(sprintf($this->NEXT_ID_SQL, $seqName));
00310         }
00311         $id = $this->insertId();
00312         if ($id) { return $id; }
00313         if ($this->execute(sprintf($this->INIT_SEQ_SQL, $seqName, $startValue))) {
00314             return $startValue;
00315         }
00316         return false;
00317     }
00318 
00327     function createSeq($seqName = 'sdboseq', $startValue = 1)
00328     {
00329         if ($this->execute(sprintf($this->CREATE_SEQ_SQL, $seqName))) {
00330             return $this->execute(sprintf($this->INIT_SEQ_SQL, $seqName, $startValue - 1));
00331         } else {
00332             return false;
00333         }
00334     }
00335 
00343     function dropSeq($seqName = 'sdboseq')
00344     {
00345         return $this->execute(sprintf($this->DROP_SEQ_SQL, $seqName));
00346     }
00347 
00353     function insertId()
00354     {
00355        return sqlite_last_insert_rowid($this->conn);
00356     }
00357 
00363     function affectedRows()
00364     {
00365         return sqlite_num_rows($this->conn);//这里仅对select有效
00366     }
00367 
00375     function fetchRow($res)
00376     {
00377         $row = sqlite_fetch_array($res);
00378         $temp = array();
00379         foreach($row as $key => $value){
00380             $key = eregi_replace('^[a-z0-9_]+\.','',$key);
00381             $temp[$key] = $value;
00382         }
00383         return $temp;
00384     }
00385 
00393     function fetchAssoc($res)
00394     {
00395         $row = sqlite_fetch_array($res,SQLITE_ASSOC);//Sqlite 没有这个功能
00396         $temp = array();
00397         foreach($row as $key => $value){
00398             $key = eregi_replace('^[a-z0-9_]+\.','',$key);
00399             $temp[$key] = $value;
00400         }
00401         return $temp;
00402     }
00403 
00411     function freeRes($res)
00412     {
00413         //return sqlite_free_result($res);
00414         return true;//sqlite 没有这样的函数
00415     }
00416 
00426     function selectLimit($sql, $length = null, $offset = null)
00427     {
00428         if (!is_null($offset)) {
00429             $sql .= "\nLIMIT " . (int)$offset;
00430             if (!is_null($length)) {
00431                 $sql .= ', ' . (int)$length;
00432             } else {
00433                 $sql .= ', 4294967294';
00434             }
00435         } elseif (!is_null($length)) {
00436             $sql .= "\nLIMIT " . (int)$length;
00437         }
00438         return $this->execute($sql);
00439     }
00440 
00448     function & getAll($sql)
00449     {
00450         if (is_resource($sql)) {
00451             $res = $sql;
00452         } else {
00453             $res = $this->execute($sql);
00454         }
00455         $data = array();
00456         while ($row = sqlite_fetch_array($res,SQLITE_ASSOC)) {
00457             $temp = array();
00458             foreach($row as $key => $value){
00459                 $key = eregi_replace('^[a-z0-9_]+\.','',$key);
00460                 $temp[$key] = $value;
00461             }
00462             $data[] = $temp;
00463         }
00464        // sqlite_free_result($res);
00465         return $data;
00466     }
00467 
00479     function & getAllGroupBy($sql, $groupBy)
00480     {
00481         if (is_resource($sql)) {
00482             $res = $sql;
00483         } else {
00484             $res = $this->execute($sql);
00485         }
00486         $data = array();
00487 
00488         $row = sqlite_fetch_array($res,SQLITE_ASSOC);
00489         if ($row != false) {
00490             $temp = array();
00491             foreach($row as $key => $value){
00492                 $key = eregi_replace('^[a-z0-9_]+\.','',$key);
00493                 $temp[$key] = $value;
00494             }
00495             $row = $temp;
00496             if ($groupBy === true) {
00497                 $groupBy = key($row);
00498             }
00499             do {
00500                 $rkv = $row[$groupBy];
00501                 unset($row[$groupBy]);
00502                 $data[$rkv][] = $row;
00503             } while ($row = sqlite_fetch_array($res,SQLITE_ASSOC));
00504         }
00505         return $data;
00506     }
00507 
00518     function getAllWithFieldRefs($sql, $field, & $fieldValues, & $reference)
00519     {
00520         if (is_resource($sql)) {
00521             $res = $sql;
00522         } else {
00523             $res = $this->execute($sql);
00524         }
00525 
00526         $fieldValues = array();
00527         $reference = array();
00528         $offset = 0;
00529         $data = array();
00530         while ($row = sqlite_fetch_array($res,SQLITE_ASSOC)) {
00531             $temp = array();
00532             foreach($row as $key => $value){
00533                 $key = eregi_replace('^[a-z0-9_]+\.','',$key);
00534                 $temp[$key] = $value;
00535             }
00536             $row = $temp;
00537             $fieldValue = $row[$field];
00538             unset($row[$field]);
00539             $data[$offset] = $row;
00540             $fieldValues[$offset] = $fieldValue;
00541             $reference[$fieldValue] =& $data[$offset];
00542             $offset++;
00543         }
00544         return $data;
00545     }
00546 
00557     function assemble($sql, & $assocRowset, $mappingName, $oneToOne, $refKeyName, $limit = null)
00558     {
00559         if (is_resource($sql)) {
00560             $res = $sql;
00561         } else {
00562             if (!is_null($limit)) {
00563                 if (is_array($limit)) {
00564                     list($length, $offset) = $limit;
00565                 } else {
00566                     $length = $limit;
00567                     $offset = 0;
00568                 }
00569                 $res = $this->selectLimit($sql, $length, $offset);
00570             } else {
00571                 $res = $this->execute($sql);
00572             }
00573         }
00574 
00575         if ($oneToOne) {
00576             // 一对一组装数据
00577             while ($row = sqlite_fetch_array($res,SQLITE_ASSOC)) {
00578                 $temp = array();
00579                 foreach($row as $key => $value){
00580                     $key = eregi_replace('^[a-z0-9_]+\.','',$key);
00581                     $temp[$key] = $value;
00582                 }
00583                 $row = $temp;
00584                 $rkv = $row[$refKeyName];
00585                 unset($row[$refKeyName]);
00586                 $assocRowset[$rkv][$mappingName] = $row;
00587             }
00588         } else {
00589             // 一对多组装数据
00590             while ($row = sqlite_fetch_array($res,SQLITE_ASSOC)) {
00591                 $rkv = $row[$refKeyName];
00592                 unset($row[$refKeyName]);
00593                 $temp = array();
00594                 foreach($row as $key => $value){
00595                     $key = eregi_replace('^[a-z0-9_]+\.','',$key);
00596                     $temp[$key] = $value;
00597                 }
00598                 $assocRowset[$rkv][$mappingName][] = $temp;
00599             }
00600         }
00601     }
00602 
00610     function getOne($sql)
00611     {
00612         if (is_resource($sql)) {
00613             $res = $sql;
00614         } else {
00615             $res = $this->execute($sql);
00616         }
00617         $row = sqlite_fetch_array($res,SQLITE_NUM);
00618         //sqlite_free_result($res);
00619         return isset($row[0]) ? $row[0] : null;
00620     }
00621 
00629     function & getRow($sql)
00630     {
00631         if (is_resource($sql)) {
00632             $res = $sql;
00633         } else {
00634             $res = $this->execute($sql);
00635         }
00636         $row = sqlite_fetch_array($res,SQLITE_ASSOC);
00637         $temp = array();
00638         foreach($row as $key => $value){
00639             $key = eregi_replace('^[a-z0-9_]+\.','',$key);
00640             $temp[$key] = $value;
00641         }
00642         return $temp;
00643     }
00644 
00653     function & getCol($sql, $col = 0)
00654     {
00655         if (is_resource($sql)) {
00656             $res = $sql;
00657         } else {
00658             $res = $this->execute($sql);
00659         }
00660         $data = array();
00661         while ($row = sqlite_fetch_array($res,SQLITE_NUM)) {
00662             $data[] = $row[$col];
00663         }
00664         return $data;
00665     }
00666 
00691     function & metaColumns($table)
00692     {
00704         static $typeMap = array(
00705             'BIT'           => 'I',
00706             'TINYINT'       => 'I',
00707             'BOOL'          => 'L',
00708             'BOOLEAN'       => 'L',
00709             'SMALLINT'      => 'I',
00710             'MEDIUMINT'     => 'I',
00711             'INT'           => 'I',
00712             'INTEGER'       => 'I',
00713             'BIGINT'        => 'I',
00714             'FLOAT'         => 'N',
00715             'DOUBLE'        => 'N',
00716             'DOUBLEPRECISION' => 'N',
00717             'FLOAT'         => 'N',
00718             'DECIMAL'       => 'N',
00719             'DEC'           => 'N',
00720 
00721             'DATE'          => 'D',
00722             'DATETIME'      => 'T',
00723             'TIMESTAMP'     => 'T',
00724             'TIME'          => 'T',
00725             'YEAR'          => 'I',
00726 
00727             'CHAR'          => 'C',
00728             'NCHAR'         => 'C',
00729             'VARCHAR'       => 'C',
00730             'NVARCHAR'      => 'C',
00731             'BINARY'        => 'B',
00732             'VARBINARY'     => 'B',
00733             'TINYBLOB'      => 'X',
00734             'TINYTEXT'      => 'X',
00735             'BLOB'          => 'X',
00736             'TEXT'          => 'X',
00737             'MEDIUMBLOB'    => 'X',
00738             'MEDIUMTEXT'    => 'X',
00739             'LONGBLOB'      => 'X',
00740             'LONGTEXT'      => 'X',
00741             'ENUM'          => 'C',
00742             'SET'           => 'C',
00743         );
00744 
00745         $rs = $this->execute(sprintf($this->META_COLUMNS_SQL, $table));
00746         if (!$rs) { return false; }
00747         $retarr = array();
00748         $sql = sqlite_fetch_array($rs);
00749         $sql = $sql[0];
00750         $firstPar   = strpos($sql, '(');
00751         $endPar     = strrpos($sql, ')')-1;
00752         $sql = substr($sql, ($firstPar+1), ($endPar - $firstPar));
00753         $sql = str_replace("\n", '', $sql);
00754         $sql = str_replace("'", '', $sql);
00755         $ligne = explode(',', $sql);
00756 
00757         //get index key
00758         $sql = "select sql from sqlite_master where type='index' and tbl_name='$table'";
00759         $rs = $this->execute($sql);
00760         $sql = sqlite_fetch_array($rs);
00761         $sql = $sql[0];
00762         $firstPar   = strpos($sql, '(');
00763         $endPar     = strrpos($sql, ')')-1;
00764         $sql = substr($sql, ($firstPar+1), ($endPar - $firstPar));
00765         $sql = str_replace("\n", '', $sql);
00766         $sql = str_replace("'", '', $sql);
00767         $temp = explode(',', $sql);
00768         $index = array();
00769         foreach ($temp as $value) {
00770             $value = trim($value);
00771             if($value){
00772                 $index[$value] = true;
00773             }
00774         }
00775 
00776         while(list($ligneNum, $cont) = each($ligne)){
00777             $row = explode(' ', trim($cont));
00778             $field = array();
00779             $field['name'] = $row[0];
00780             $type = $row[1];
00781             $field['scale'] = null;
00782             $queryArray = false;
00783             if (preg_match('/^(.+)\((\d+),(\d+)/', $type, $queryArray)) {
00784                 $field['type'] = $queryArray[1];
00785                 $field['maxLength'] = is_numeric($queryArray[2]) ? $queryArray[2] : -1;
00786                 $field['scale'] = is_numeric($queryArray[3]) ? $queryArray[3] : -1;
00787             } elseif (preg_match('/^(.+)\((\d+)/', $type, $queryArray)) {
00788                 $field['type'] = $queryArray[1];
00789                 $field['maxLength'] = is_numeric($queryArray[2]) ? $queryArray[2] : -1;
00790             } elseif (preg_match('/^(enum)\((.*)\)$/i', $type, $queryArray)) {
00791                 $field['type'] = $queryArray[1];
00792                 $arr = explode(",",$queryArray[2]);
00793                 $field['enums'] = $arr;
00794                 $zlen = max(array_map("strlen",$arr)) - 2; // PHP >= 4.0.6
00795                 $field['maxLength'] = ($zlen > 0) ? $zlen : 1;
00796             } else {
00797                 $field['type'] = $type;
00798                 $field['maxLength'] = -1;
00799             }
00800             $field['simpleType'] = $typeMap[strtoupper($field['type'])];
00801             if ($field['simpleType'] == 'C' && $field['maxLength'] > 250) {
00802                 $field['simpleType'] = 'X';
00803             }
00804 
00805             $temp = eregi('PRIMARY[[:space:]]KEY', $cont);
00806             $field['primaryKey'] = $temp || $index[$row[0]];
00807             $field['notNull'] = $field['primaryKey'] || (strtoupper($row[2]) == 'NOT');
00808             $field['autoIncrement'] = $temp;
00809             if ($field['autoIncrement']) { $field['simpleType'] = 'R'; }
00810             $field['binary'] = (strpos($type,'blob') !== false);
00811             $field['unsigned'] = (strpos($type,'unsigned') !== false);
00812 
00813             if (!$field['binary']) {
00814                 $d = $row[4];
00815                 if ($d != '' && $d != 'NULL') {
00816                     $field['hasDefault'] = true;
00817                     $field['defaultValue'] = $d;
00818                 } else {
00819                     $field['hasDefault'] = false;
00820                 }
00821             }
00822             $retarr[strtoupper($field['name'])] = $field;
00823 
00824         }
00825         return $retarr;
00826     }
00827 
00833     function dbTimeStamp($timestamp)
00834     {
00835         return date('Y-m-d H:i:s', $timestamp);
00836     }
00837 
00841     function startTrans()
00842     {
00843     }
00844 
00853     function completeTrans($commitOnNoErrors = true)
00854     {
00855         return false;
00856     }
00857 
00861     function failTrans()
00862     {
00863         $this->_transCommit = false;
00864     }
00865 
00869     function hasFailedTrans()
00870     {
00871         return true;
00872     }
00873 
00882     function _prepareSql($sql, & $inputarr)
00883     {
00884         $sqlarr = explode('?', $sql);
00885         $sql = '';
00886         $ix = 0;
00887         foreach ($inputarr as $v) {
00888             $sql .= $sqlarr[$ix];
00889             $typ = gettype($v);
00890             if ($typ == 'string') {
00891                 $sql .= $this->qstr($v);
00892             } else if ($typ == 'double') {
00893                 $sql .= $this->qstr(str_replace(',', '.', $v));
00894             } else if ($typ == 'boolean') {
00895                 $sql .= $v ? $this->TRUE_VALUE : $this->FALSE_VALUE;
00896             } else if (is_null($v)) {
00897                 $sql .= 'NULL';
00898             } else {
00899                 $sql .= $v;
00900             }
00901             $ix += 1;
00902         }
00903         if (isset($sqlarr[$ix])) {
00904             $sql .= $sqlarr[$ix];
00905         }
00906         return $sql;
00907     }
00908 }

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