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'";
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
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;
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);
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);
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
00414 return true;
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
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
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
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;
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 }