This repository has been archived on 2024-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
khosb/includes/adodb/drivers/adodb-pdo_sqlite.inc.php
2008-11-26 14:50:40 -08:00

268 lines
9.6 KiB
PHP

<?php
/*
V5.06 16 Oct 2008 (c) 2000-2008 John Lim (jlim#natsoft.com). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence. See License.txt.
Set tabs to 4 for best viewing.
Latest version is available at http://adodb.sourceforge.net
Thanks Diogo Toscano (diogo#scriptcase.net) for the code.
*/
class ADODB_pdo_sqlite extends ADODB_pdo {
var $metaTablesSQL = "SELECT name FROM sqlite_master WHERE type='table'";
var $sysDate = 'current_date';
var $sysTimeStamp = 'current_timestamp';
var $nameQuote = '`';
var $replaceQuote = "''";
var $hasTransactions = true;
var $_bndInputArray = false;
var $hasInsertID = true;
var $hasGenID = true;
var $_genSeqSQL = "create table %s (id integer)";
var $_genSeqCountSQL = 'select count(*) from %s';
var $_genSeq2SQL = 'insert into %s values(%s)';
var $_dropSeqSQL = 'drop table %s';
var $_stmt = false;
function _init($parentDriver)
{
$parentDriver->_bindInputArray = true;
}
function _query($sql,$inputarr=false) {
if(strtolower(substr($sql,0,5)) != 'alter') {
return parent::_query($sql,$inputarr);
} else {
if(!$this->sqliteDropColumn($sql))
return parent::_query($sql,$inputarr);
else
return true;
}
}
function _connect($argDSN, $argUsername, $argPassword, $argDatabasename, $persist=false) {
return parent::_connect($argDatabasename,'','','',$persist);
}
function sqliteDropColumn($sql) {
$queryparts = preg_split("/[\s]+/",$sql,10,PREG_SPLIT_NO_EMPTY);
if(count($queryparts) == 6) {
$table = $queryparts[2];
$temp_table = $table.'_Temp';
$removeColumn = $queryparts[5];
$removeColumn = str_replace(';','',$removeColumn);
if(strtolower($queryparts[1]) != 'table' ||
strtolower($queryparts[3]) != 'drop' ||
strtolower($queryparts[4]) != 'column') {
return false;
} else {
// RENAME TABLE to TABLE_Temp
// CREATE new table without dropped column
// INSERT RECORDS from old table to new
// DROP Temp table
$meta = $this->MetaColumns($table);
$fields = Array();
$fieldNames = Array();
foreach($meta as $col) {
if($col->name != $removeColumn) {
$colText = $col->name;
if(!empty($col->type))
$colText .= ' '.$col->type;
if($col->not_null)
$colText .= ' NOT NULL';
if(!empty($col->default_value))
$colText .= ' DEFAULT '.$col->default_value.'';
$fieldNames[] = $col->name;
$fields[] = $colText;
}
}
$fieldList = implode(',',$fields);
$fieldNameList = implode(',',$fieldNames);
$this->BeginTrans();
$sql = "SELECT sql FROM sqlite_master WHERE type = 'index' AND tbl_name = '$table'";
$result = $this->Execute($sql);
while(list($index) = $result->FetchRow()) {
$indexes[] = $index;
}
$renameTempSql = 'ALTER TABLE '.$table.' RENAME TO '.$temp_table.';';
$createTableSql = 'CREATE TABLE '.$table.'('.$fieldList.');';
$copyTableContentsSql = 'INSERT INTO '.$table.' SELECT '.$fieldNameList.' FROM '.$temp_table.';';
$removeTableSql = 'DROP TABLE '.$temp_table.';';
$vacuumSql = 'VACUUM '.$table.';';
// Do the steps to drop the column by renaming and creating new table
$ok = $this->Execute($renameTempSql);
if($ok) $ok = $this->Execute($createTableSql);
if($ok) $ok = $this->Execute($copyTableContentsSql);
$this->CommitTrans($ok);
if($ok) $ok = $this->Execute($removeTableSql);
if($ok) $ok = $this->Execute($vacuumSql);
// Recreate the indexes on the new table from the old
foreach($indexes as $indexSQL) {
$listStart = strpos($indexSQL,'(')+1;
$listEnd = strpos($indexSQL,')');
$indexList = substr($indexSQL,$listStart,$listEnd-$listStart);
$indexList = explode(',',$indexList);
$newIndexList = Array();
foreach($indexList as $listItem) {
$listItem = trim($listItem);
if($listItem != $removeColumn) {
$newIndexList[] = $listItem;
}
}
$indexSQL = substr($indexSQL,0,$listStart-1);
$indexSQL .= '('.implode(',',$newIndexList).');';
$this->Execute($indexSQL);
}
return $ok;
}
}
return false;
}
function &SelectLimit($sql,$nrows=-1,$offset=-1,$inputarr=false,$secs=0) {
$offsetStr =($offset>=0) ? "$offset," : '';
if ($secs)
$rs =& $this->CacheExecute($secs,$sql." LIMIT $offsetStr$nrows",$inputarr);
else
$rs =& $this->Execute($sql." LIMIT $offsetStr$nrows",$inputarr);
return $rs;
}
function GenID($seq='adodbseq',$start=1) {
// if you have to modify the parameter below, your database is overloaded,
// or you need to implement generation of id's yourself!
$MAXLOOPS = 100;
//$this->debug=1;
while (--$MAXLOOPS>=0) {
@($num = array_pop($this->GetCol("select id from $seq")));
if ($num === false || !is_numeric($num)) {
@$this->Execute(sprintf($this->_genSeqSQL ,$seq));
$start -= 1;
$num = '0';
$cnt = $this->GetOne(sprintf($this->_genSeqCountSQL,$seq));
if (!$cnt) {
$ok = $this->Execute(sprintf($this->_genSeq2SQL,$seq,$start));
}
if (!$ok) return false;
}
$this->Execute("update $seq set id=id+1");
if ($this->affected_rows() > 0) {
$num += 1;
$this->genID = intval($num);
return intval($num);
}
}
if ($fn = $this->raiseErrorFn) {
$fn($this->databaseType,'GENID',-32000,"Unable to generate unique id after $MAXLOOPS attempts",$seq,$num);
}
return false;
}
function BeginTrans()
{
if (!$this->hasTransactions) return false;
if ($this->transOff) return true;
if($this->transCnt < 1) {
$this->transCnt += 1;
$this->_autocommit = false;
return $this->_connectionID->beginTransaction();
}
}
function CommitTrans($ok=true)
{
if (!$this->hasTransactions) return false;
if ($this->transOff) return true;
if (!$ok) return $this->RollbackTrans();
if ($this->transCnt) $this->transCnt -= 1;
$this->_autocommit = true;
if($this->transCnt == 0)
$ret = $this->_connectionID->commit();
return $ret;
}
function RollbackTrans()
{
if (!$this->hasTransactions) return false;
if ($this->transOff) return true;
if ($this->transCnt) $this->transCnt -= 1;
$this->_autocommit = true;
$ret = $this->_connectionID->rollback();
return $ret;
}
function CreateSequence($seqname='adodbseq',$start=1) {
if (empty($this->_genSeqSQL)) return false;
$ok = $this->Execute(sprintf($this->_genSeqSQL,$seqname));
if (!$ok) return false;
$start -= 1;
return $this->Execute("insert into $seqname values($start)");
}
function DropSequence($seqname) {
if (empty($this->_dropSeqSQL)) return false;
return $this->Execute(sprintf($this->_dropSeqSQL,$seqname));
}
// mark newnham
function &MetaColumns($tab)
{
global $ADODB_FETCH_MODE;
$false = false;
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false);
$rs = $this->Execute("PRAGMA table_info('$tab')");
if (isset($savem)) $this->SetFetchMode($savem);
if (!$rs) {
$ADODB_FETCH_MODE = $save;
return $false;
}
$arr = array();
while ($r = $rs->FetchRow()) {
$type = explode('(',$r['type']);
$size = '';
if (sizeof($type)==2)
$size = trim($type[1],')');
$fn = strtoupper($r['name']);
$fld = new ADOFieldObject;
$fld->name = $r['name'];
$fld->type = $type[0];
$fld->max_length = $size;
$fld->not_null = $r['notnull'];
$fld->primary_key = $r['pk'];
$fld->default_value = $r['dflt_value'];
$fld->scale = 0;
if ($save == ADODB_FETCH_NUM) $arr[] = $fld;
else $arr[strtoupper($fld->name)] = $fld;
}
$rs->Close();
$ADODB_FETCH_MODE = $save;
return $arr;
}
function MetaTables($ttype=false,$showSchema=false,$mask=false) {
return $this->GetCol($this->metaTablesSQL);
}
function __sleep() {
unset($this->_connectionID);
return( array_keys( get_object_vars( $this ) ) );
}
}
?>