1a1e6784eSAndreas Gohr<?php 2a1e6784eSAndreas Gohr/** 3a1e6784eSAndreas Gohr * DokuWiki Plugin sqlite (Helper Component) 4a1e6784eSAndreas Gohr * 5a1e6784eSAndreas Gohr * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 6a1e6784eSAndreas Gohr * @author Andreas Gohr <gohr@cosmocode.de> 7a1e6784eSAndreas Gohr */ 8a1e6784eSAndreas Gohr 9a1e6784eSAndreas Gohr// must be run within Dokuwiki 10a1e6784eSAndreas Gohrif(!defined('DOKU_INC')) die(); 11a1e6784eSAndreas Gohr 1287fa2c18Sstretchyboyif(!defined('DOKU_EXT_SQLITE')) define('DOKU_EXT_SQLITE', 'sqlite'); 1387fa2c18Sstretchyboyif(!defined('DOKU_EXT_PDO')) define('DOKU_EXT_PDO', 'pdo'); 14c137e95fSAndreas Gohrif(!defined('DOKU_EXT_NULL')) define('DOKU_EXT_NULL', 'null'); 1587fa2c18Sstretchyboy 16aa81d781SKlap-inrequire_once(DOKU_PLUGIN.'sqlite/classes/adapter.php'); 1787fa2c18Sstretchyboy 183e9ac593SGerrit Uitslag/** 193e9ac593SGerrit Uitslag * Class helper_plugin_sqlite 203e9ac593SGerrit Uitslag */ 21a1e6784eSAndreas Gohrclass helper_plugin_sqlite extends DokuWiki_Plugin { 224b4b2db0SGerrit Uitslag /** @var helper_plugin_sqlite_adapter_pdosqlite|helper_plugin_sqlite_adapter|\helper_plugin_sqlite_adapter_sqlite2|null */ 23*6c7ee3f2SAndreas Gohr protected $adapter = null; 24aa81d781SKlap-in 253e9ac593SGerrit Uitslag /** 26*6c7ee3f2SAndreas Gohr * @return helper_plugin_sqlite_adapter_pdosqlite|helper_plugin_sqlite_adapter|\helper_plugin_sqlite_adapter_sqlite2|null 273e9ac593SGerrit Uitslag */ 28ca2f2adaSKlap-in public function getAdapter() { 29ca2f2adaSKlap-in return $this->adapter; 30ca2f2adaSKlap-in } 31ca2f2adaSKlap-in 32a1e6784eSAndreas Gohr /** 33aa81d781SKlap-in * Keep separate instances for every call to keep database connections 34aa81d781SKlap-in */ 35aa81d781SKlap-in public function isSingleton() { 36aa81d781SKlap-in return false; 37aa81d781SKlap-in } 38aa81d781SKlap-in 39aa81d781SKlap-in /** 40a1e6784eSAndreas Gohr * constructor 41a1e6784eSAndreas Gohr */ 42aa81d781SKlap-in public function helper_plugin_sqlite() { 4387fa2c18Sstretchyboy 4413896259SKlap-in if(!$this->adapter) { 45b0653a7eSAndreas Gohr if($this->existsPDOSqlite() && empty($_ENV['SQLITE_SKIP_PDO'])) { 46aa81d781SKlap-in require_once(DOKU_PLUGIN.'sqlite/classes/adapter_pdosqlite.php'); 47aa81d781SKlap-in $this->adapter = new helper_plugin_sqlite_adapter_pdosqlite(); 48aa81d781SKlap-in } 49aa81d781SKlap-in } 50aa81d781SKlap-in 5113896259SKlap-in if(!$this->adapter) { 52aa81d781SKlap-in if($this->existsSqlite2()) { 53aa81d781SKlap-in require_once(DOKU_PLUGIN.'sqlite/classes/adapter_sqlite2.php'); 54aa81d781SKlap-in $this->adapter = new helper_plugin_sqlite_adapter_sqlite2(); 55aa81d781SKlap-in } 56aa81d781SKlap-in } 57aa81d781SKlap-in 5813896259SKlap-in if(!$this->adapter) { 59aa81d781SKlap-in msg('SQLite & PDO SQLite support missing in this PHP install - plugin will not work', -1); 60aa81d781SKlap-in } 61aa81d781SKlap-in } 62aa81d781SKlap-in 63aa81d781SKlap-in /** 64aa81d781SKlap-in * check availabilty of PHPs sqlite extension (for sqlite2 support) 65aa81d781SKlap-in */ 66aa81d781SKlap-in public function existsSqlite2() { 67aa81d781SKlap-in if(!extension_loaded('sqlite')) { 68aa81d781SKlap-in $prefix = (PHP_SHLIB_SUFFIX === 'dll') ? 'php_' : ''; 69aa81d781SKlap-in if(function_exists('dl')) @dl($prefix.'sqlite.'.PHP_SHLIB_SUFFIX); 70aa81d781SKlap-in } 71aa81d781SKlap-in 72aa81d781SKlap-in return function_exists('sqlite_open'); 73aa81d781SKlap-in } 74aa81d781SKlap-in 75aa81d781SKlap-in /** 76aa81d781SKlap-in * check availabilty of PHP PDO sqlite3 77aa81d781SKlap-in */ 78aa81d781SKlap-in public function existsPDOSqlite() { 7987fa2c18Sstretchyboy if(!extension_loaded('pdo_sqlite')) { 8087fa2c18Sstretchyboy $prefix = (PHP_SHLIB_SUFFIX === 'dll') ? 'php_' : ''; 8187fa2c18Sstretchyboy if(function_exists('dl')) @dl($prefix.'pdo_sqlite.'.PHP_SHLIB_SUFFIX); 8287fa2c18Sstretchyboy } 8387fa2c18Sstretchyboy 8487fa2c18Sstretchyboy if(class_exists('pdo')) { 85aa81d781SKlap-in foreach(PDO::getAvailableDrivers() as $driver) { 86aa81d781SKlap-in if($driver == 'sqlite') { 87aa81d781SKlap-in return true; 8887fa2c18Sstretchyboy } 8987fa2c18Sstretchyboy } 907ed6069fSAdrian Lang } 91aa81d781SKlap-in return false; 92a1e6784eSAndreas Gohr } 93a1e6784eSAndreas Gohr 94a1e6784eSAndreas Gohr /** 95a1e6784eSAndreas Gohr * Initializes and opens the database 96a1e6784eSAndreas Gohr * 97a1e6784eSAndreas Gohr * Needs to be called right after loading this helper plugin 98aa81d781SKlap-in * 99aa81d781SKlap-in * @param string $dbname 100aa81d781SKlap-in * @param string $updatedir - Database update infos 101aa81d781SKlap-in * @return bool 102a1e6784eSAndreas Gohr */ 103aa81d781SKlap-in public function init($dbname, $updatedir) { 104aa81d781SKlap-in $init = null; // set by initdb() 105c137e95fSAndreas Gohr if( !$this->adapter or !$this->adapter->initdb($dbname, $init) ){ 106c137e95fSAndreas Gohr require_once(DOKU_PLUGIN.'sqlite/classes/adapter_null.php'); 107c137e95fSAndreas Gohr $this->adapter = new helper_plugin_sqlite_adapter_null(); 108c137e95fSAndreas Gohr return false; 109c137e95fSAndreas Gohr } 110a1e6784eSAndreas Gohr 111a4680e7bSGerrit Uitslag $this->create_function('GETACCESSLEVEL', array($this, '_getAccessLevel'), 1); 112a4680e7bSGerrit Uitslag 113aa81d781SKlap-in return $this->_updatedb($init, $updatedir); 114a1e6784eSAndreas Gohr } 115a1e6784eSAndreas Gohr 116a1e6784eSAndreas Gohr /** 117a1e6784eSAndreas Gohr * Return the current Database Version 118a1e6784eSAndreas Gohr */ 119aa81d781SKlap-in private function _currentDBversion() { 120a1e6784eSAndreas Gohr $sql = "SELECT val FROM opts WHERE opt = 'dbversion';"; 121a1e6784eSAndreas Gohr $res = $this->query($sql); 122a1e6784eSAndreas Gohr if(!$res) return false; 123a1e6784eSAndreas Gohr $row = $this->res2row($res, 0); 124a1e6784eSAndreas Gohr return (int) $row['val']; 125a1e6784eSAndreas Gohr } 126aa81d781SKlap-in 127a1e6784eSAndreas Gohr /** 128a1e6784eSAndreas Gohr * Update the database if needed 129a1e6784eSAndreas Gohr * 130a1e6784eSAndreas Gohr * @param bool $init - true if this is a new database to initialize 131a1e6784eSAndreas Gohr * @param string $updatedir - Database update infos 132aa81d781SKlap-in * @return bool 133a1e6784eSAndreas Gohr */ 13413896259SKlap-in private function _updatedb($init, $updatedir) { 135a1e6784eSAndreas Gohr if($init) { 1364d9093b4Sstretchyboy 137a1e6784eSAndreas Gohr $current = 0; 138a1e6784eSAndreas Gohr } else { 139a1e6784eSAndreas Gohr $current = $this->_currentDBversion(); 140a1e6784eSAndreas Gohr if(!$current) { 141aa81d781SKlap-in msg("SQLite: no DB version found. '".$this->adapter->getDbname()."' DB probably broken.", -1); 142a1e6784eSAndreas Gohr return false; 143a1e6784eSAndreas Gohr } 144a1e6784eSAndreas Gohr } 145a1e6784eSAndreas Gohr 146a1e6784eSAndreas Gohr // in case of init, add versioning table 147a1e6784eSAndreas Gohr if($init) { 148a1e6784eSAndreas Gohr if(!$this->_runupdatefile(dirname(__FILE__).'/db.sql', 0)) { 149aa81d781SKlap-in msg("SQLite: '".$this->adapter->getDbname()."' database upgrade failed for version ", -1); 150a1e6784eSAndreas Gohr return false; 151a1e6784eSAndreas Gohr } 152a1e6784eSAndreas Gohr } 153a1e6784eSAndreas Gohr 154a1e6784eSAndreas Gohr $latest = (int) trim(io_readFile($updatedir.'/latest.version')); 155a1e6784eSAndreas Gohr 156a1e6784eSAndreas Gohr // all up to date? 157a1e6784eSAndreas Gohr if($current >= $latest) return true; 158a1e6784eSAndreas Gohr for($i = $current + 1; $i <= $latest; $i++) { 159a1e6784eSAndreas Gohr $file = sprintf($updatedir.'/update%04d.sql', $i); 160a1e6784eSAndreas Gohr if(file_exists($file)) { 161a1e6784eSAndreas Gohr if(!$this->_runupdatefile($file, $i)) { 162aa81d781SKlap-in msg("SQLite: '".$this->adapter->getDbname()."' database upgrade failed for version ".$i, -1); 163a1e6784eSAndreas Gohr return false; 164a1e6784eSAndreas Gohr } 165*6c7ee3f2SAndreas Gohr } else { 166*6c7ee3f2SAndreas Gohr msg("SQLite: update file $file not found, skipped.", -1); 167a1e6784eSAndreas Gohr } 168a1e6784eSAndreas Gohr } 169a1e6784eSAndreas Gohr return true; 170a1e6784eSAndreas Gohr } 171a1e6784eSAndreas Gohr 172a1e6784eSAndreas Gohr /** 173a1e6784eSAndreas Gohr * Updates the database structure using the given file to 174a1e6784eSAndreas Gohr * the given version. 175a1e6784eSAndreas Gohr */ 176aa81d781SKlap-in private function _runupdatefile($file, $version) { 177*6c7ee3f2SAndreas Gohr if(!file_exists($file)) { 178*6c7ee3f2SAndreas Gohr msg("SQLite: Failed to find DB update file $file"); 179*6c7ee3f2SAndreas Gohr return false; 180*6c7ee3f2SAndreas Gohr } 181a1e6784eSAndreas Gohr $sql = io_readFile($file, false); 182a1e6784eSAndreas Gohr 183f10ea6c1SKlap-in $sql = $this->SQLstring2array($sql); 184a1e6784eSAndreas Gohr array_unshift($sql, 'BEGIN TRANSACTION'); 185a1e6784eSAndreas Gohr array_push($sql, "INSERT OR REPLACE INTO opts (val,opt) VALUES ($version,'dbversion')"); 186a1e6784eSAndreas Gohr array_push($sql, "COMMIT TRANSACTION"); 187a1e6784eSAndreas Gohr 188f10ea6c1SKlap-in if(!$this->doTransaction($sql)) { 189f10ea6c1SKlap-in return false; 190f10ea6c1SKlap-in } 191f10ea6c1SKlap-in return ($version == $this->_currentDBversion()); 192f10ea6c1SKlap-in } 193f10ea6c1SKlap-in 194f10ea6c1SKlap-in /** 195a4680e7bSGerrit Uitslag * Callback checks the permissions for the current user 196a4680e7bSGerrit Uitslag * 197a4680e7bSGerrit Uitslag * This function is registered as a SQL function named GETACCESSLEVEL 198a4680e7bSGerrit Uitslag * 199a4680e7bSGerrit Uitslag * @param string $pageid page ID (needs to be resolved and cleaned) 200a4680e7bSGerrit Uitslag * @return int permission level 201a4680e7bSGerrit Uitslag */ 202a4680e7bSGerrit Uitslag public function _getAccessLevel($pageid) { 203a4680e7bSGerrit Uitslag static $aclcache = array(); 204a4680e7bSGerrit Uitslag 205a4680e7bSGerrit Uitslag if(isset($aclcache[$pageid])) { 206a4680e7bSGerrit Uitslag return $aclcache[$pageid]; 207a4680e7bSGerrit Uitslag } 208a4680e7bSGerrit Uitslag 209a4680e7bSGerrit Uitslag if(isHiddenPage($pageid)) { 210a4680e7bSGerrit Uitslag $acl = AUTH_NONE; 211a4680e7bSGerrit Uitslag } else { 212a4680e7bSGerrit Uitslag $acl = auth_quickaclcheck($pageid); 213a4680e7bSGerrit Uitslag } 214a4680e7bSGerrit Uitslag $aclcache[$pageid] = $acl; 215a4680e7bSGerrit Uitslag return $acl; 216a4680e7bSGerrit Uitslag } 217a4680e7bSGerrit Uitslag 218a4680e7bSGerrit Uitslag /** 219f10ea6c1SKlap-in * Split sql queries on semicolons, unless when semicolons are quoted 220f10ea6c1SKlap-in * 221f10ea6c1SKlap-in * @param string $sql 222f10ea6c1SKlap-in * @return array sql queries 223f10ea6c1SKlap-in */ 224f10ea6c1SKlap-in public function SQLstring2array($sql) { 2253fb592daSAndreas Gohr $statements = array(); 2263fb592daSAndreas Gohr $len = strlen($sql); 2273fb592daSAndreas Gohr 2283fb592daSAndreas Gohr // Simple state machine to "parse" sql into single statements 2293fb592daSAndreas Gohr $in_str = false; 2303fb592daSAndreas Gohr $in_com = false; 2313fb592daSAndreas Gohr $statement = ''; 2323fb592daSAndreas Gohr for($i=0; $i<$len; $i++){ 2333fb592daSAndreas Gohr $prev = $i ? $sql{$i-1} : "\n"; 2343fb592daSAndreas Gohr $char = $sql{$i}; 2353fb592daSAndreas Gohr $next = $sql{$i+1}; 2363fb592daSAndreas Gohr 2373fb592daSAndreas Gohr // in comment? ignore everything until line end 2383fb592daSAndreas Gohr if($in_com){ 2393fb592daSAndreas Gohr if($char == "\n"){ 2403fb592daSAndreas Gohr $in_com = false; 2413fb592daSAndreas Gohr } 2423fb592daSAndreas Gohr continue; 2433fb592daSAndreas Gohr } 2443fb592daSAndreas Gohr 2453fb592daSAndreas Gohr // handle strings 2463fb592daSAndreas Gohr if($in_str){ 2475922cb27SAndreas Gohr if($char == "'"){ 2485922cb27SAndreas Gohr if($next == "'"){ 2495922cb27SAndreas Gohr // current char is an escape for the next 2503fb592daSAndreas Gohr $statement .= $char . $next; 2513fb592daSAndreas Gohr $i++; 2523fb592daSAndreas Gohr continue; 2535922cb27SAndreas Gohr }else{ 2545922cb27SAndreas Gohr // end of string 2553fb592daSAndreas Gohr $statement .= $char; 2563fb592daSAndreas Gohr $in_str = false; 2573fb592daSAndreas Gohr continue; 2583fb592daSAndreas Gohr } 2595922cb27SAndreas Gohr } 2603fb592daSAndreas Gohr // still in string 2613fb592daSAndreas Gohr $statement .= $char; 2623fb592daSAndreas Gohr continue; 2633fb592daSAndreas Gohr } 2643fb592daSAndreas Gohr 2653fb592daSAndreas Gohr // new comment? 2663fb592daSAndreas Gohr if($char == '-' && $next == '-' && $prev == "\n"){ 2673fb592daSAndreas Gohr $in_com = true; 2683fb592daSAndreas Gohr continue; 2693fb592daSAndreas Gohr } 2703fb592daSAndreas Gohr 2713fb592daSAndreas Gohr // new string? 2725922cb27SAndreas Gohr if($char == "'"){ 2735922cb27SAndreas Gohr $in_str = true; 2743fb592daSAndreas Gohr $statement .= $char; 2753fb592daSAndreas Gohr continue; 2763fb592daSAndreas Gohr } 2773fb592daSAndreas Gohr 2783fb592daSAndreas Gohr // the real delimiter 2793fb592daSAndreas Gohr if($char == ';'){ 2803fb592daSAndreas Gohr $statements[] = trim($statement); 2813fb592daSAndreas Gohr $statement = ''; 2823fb592daSAndreas Gohr continue; 2833fb592daSAndreas Gohr } 2843fb592daSAndreas Gohr 2853fb592daSAndreas Gohr // some standard query stuff 2863fb592daSAndreas Gohr $statement .= $char; 2873fb592daSAndreas Gohr } 2883fb592daSAndreas Gohr if($statement) $statements[] = trim($statement); 2893fb592daSAndreas Gohr 2903fb592daSAndreas Gohr return $statements; 291f10ea6c1SKlap-in } 292f10ea6c1SKlap-in 293f10ea6c1SKlap-in /** 294f10ea6c1SKlap-in * @param array $sql queries without terminating semicolon 295f10ea6c1SKlap-in * @param bool $sqlpreparing 296f10ea6c1SKlap-in * @return bool 297f10ea6c1SKlap-in */ 298f10ea6c1SKlap-in public function doTransaction($sql, $sqlpreparing = true) { 299a1e6784eSAndreas Gohr foreach($sql as $s) { 300a1e6784eSAndreas Gohr $s = preg_replace('!^\s*--.*$!m', '', $s); 301a1e6784eSAndreas Gohr $s = trim($s); 302a1e6784eSAndreas Gohr if(!$s) continue; 303fd69a32cSAndreas Gohr 304f10ea6c1SKlap-in if($sqlpreparing) { 305a1e6784eSAndreas Gohr $res = $this->query("$s;"); 306f10ea6c1SKlap-in } else { 307f10ea6c1SKlap-in $res = $this->adapter->executeQuery("$s;"); 308f10ea6c1SKlap-in } 309a1e6784eSAndreas Gohr if($res === false) { 310f10ea6c1SKlap-in //TODO check rollback for sqlite PDO 31113896259SKlap-in if($this->adapter->getName() == DOKU_EXT_SQLITE) { 3121dc19626SKlap-in $this->query('ROLLBACK TRANSACTION'); 313*6c7ee3f2SAndreas Gohr } else { 314*6c7ee3f2SAndreas Gohr $err = $this->adapter->getDb()->errorInfo(); 315*6c7ee3f2SAndreas Gohr msg($err[0].' '.$err[1].' '.$err[2].':<br /><pre>'.hsc($s).'</pre>', -1); 316a1e6784eSAndreas Gohr } 31705f176edSstretchyboy return false; 31805f176edSstretchyboy } 319a1e6784eSAndreas Gohr } 320f10ea6c1SKlap-in return true; 321a1e6784eSAndreas Gohr } 322a1e6784eSAndreas Gohr 323a34ef333SKlap-in /** 324a34ef333SKlap-in * Dump db into a file in meta directory 325a34ef333SKlap-in * 326a34ef333SKlap-in */ 327a34ef333SKlap-in public function dumpDatabase($dbname, $from = DOKU_EXT_SQLITE) { 328a34ef333SKlap-in global $conf; 329a34ef333SKlap-in $adapterDumpDb = null; 330a34ef333SKlap-in //connect to desired database 331a34ef333SKlap-in if($this->adapter->getName() == $from) { 332a34ef333SKlap-in $adapterDumpDb =& $this->adapter; 333a34ef333SKlap-in } else { 334a34ef333SKlap-in if($from == DOKU_EXT_SQLITE) { 335a34ef333SKlap-in //TODO test connecting to sqlite2 database 336a34ef333SKlap-in if($this->existsSqlite2()) { 337a34ef333SKlap-in require_once(DOKU_PLUGIN.'sqlite/classes/adapter_sqlite2.php'); 338a34ef333SKlap-in $adapterDumpDb = new helper_plugin_sqlite_adapter_sqlite2(); 339a34ef333SKlap-in } else { 340a34ef333SKlap-in msg('PHP Sqlite Extension(needed for sqlite2) not available, database "'.hsc($dbname).'" is not dumped to file.'); 341a34ef333SKlap-in return false; 342a34ef333SKlap-in } 343a34ef333SKlap-in } 344a34ef333SKlap-in } 345a34ef333SKlap-in if($adapterDumpDb === null) { 346a34ef333SKlap-in msg('No adapter loaded'); 347a34ef333SKlap-in return false; 348a34ef333SKlap-in } 349a34ef333SKlap-in $init = false; 350a34ef333SKlap-in if(!$adapterDumpDb->initdb($dbname, $init)) { 351a34ef333SKlap-in msg('Opening database fails.', -1); 352a34ef333SKlap-in return false; 353a34ef333SKlap-in } 354f10ea6c1SKlap-in 355a34ef333SKlap-in $res = $adapterDumpDb->query(array("SELECT name,sql FROM sqlite_master WHERE type='table'")); 356a34ef333SKlap-in $tables = $adapterDumpDb->res2arr($res); 357a34ef333SKlap-in 358a34ef333SKlap-in $filename = $conf['metadir'].'/dumpfile_'.$dbname.'.sql'; 359a34ef333SKlap-in if($fp = fopen($filename, 'w')) { 360a34ef333SKlap-in 361a34ef333SKlap-in fwrite($fp, 'BEGIN TRANSACTION;'."\n"); 362a34ef333SKlap-in 363a34ef333SKlap-in foreach($tables as $table) { 364a34ef333SKlap-in 365a34ef333SKlap-in fwrite($fp, $table['sql'].";\n"); 366a34ef333SKlap-in 367a34ef333SKlap-in $sql = "SELECT * FROM ".$table['name']; 368a34ef333SKlap-in $res = $adapterDumpDb->query(array($sql)); 369a34ef333SKlap-in 370a34ef333SKlap-in while($row = $adapterDumpDb->res_fetch_array($res)) { 371a34ef333SKlap-in 372a34ef333SKlap-in $line = 'INSERT INTO '.$table['name'].' VALUES('; 373a34ef333SKlap-in foreach($row as $no_entry => $entry) { 374a34ef333SKlap-in if($no_entry !== 0) { 375a34ef333SKlap-in $line .= ','; 376a34ef333SKlap-in } 377a34ef333SKlap-in 378a34ef333SKlap-in if(is_null($entry)) { 379a34ef333SKlap-in $line .= 'NULL'; 380a34ef333SKlap-in } elseif(!is_numeric($entry)) { 381a34ef333SKlap-in $line .= $adapterDumpDb->quote_string($entry); 382a34ef333SKlap-in } else { 383a34ef333SKlap-in //TODO depending on locale extra leading zeros are truncated e.g 1.300 (thousand three hunderd)-> 1.3 384a34ef333SKlap-in $line .= $entry; 385a34ef333SKlap-in } 386a34ef333SKlap-in } 387a34ef333SKlap-in $line .= ');'."\n"; 388a34ef333SKlap-in 389a34ef333SKlap-in fwrite($fp, $line); 390a34ef333SKlap-in } 391a34ef333SKlap-in } 392a34ef333SKlap-in 393a34ef333SKlap-in $res = $adapterDumpDb->query(array("SELECT name,sql FROM sqlite_master WHERE type='index'")); 394a34ef333SKlap-in $indexes = $adapterDumpDb->res2arr($res); 395a34ef333SKlap-in foreach($indexes as $index) { 396a34ef333SKlap-in fwrite($fp, $index['sql'].";\n"); 397a34ef333SKlap-in } 398a34ef333SKlap-in 399a34ef333SKlap-in fwrite($fp, 'COMMIT;'."\n"); 400a34ef333SKlap-in 401a34ef333SKlap-in fclose($fp); 402a34ef333SKlap-in return $filename; 403a34ef333SKlap-in } else { 404a34ef333SKlap-in msg('Dumping "'.hsc($dbname).'" has failed. Could not open '.$filename); 405a34ef333SKlap-in return false; 406a34ef333SKlap-in } 407a34ef333SKlap-in } 408a34ef333SKlap-in 409a34ef333SKlap-in /** 410a34ef333SKlap-in * Read $dumpfile and try to add it to database. 411a34ef333SKlap-in * A existing database is backuped first as e.g. dbname.copy2.sqlite3 412a34ef333SKlap-in * 413a34ef333SKlap-in * @param string $dbname 414a34ef333SKlap-in * @param string $dumpfile 415a34ef333SKlap-in * @return bool true on succes 416a34ef333SKlap-in */ 417a34ef333SKlap-in public function fillDatabaseFromDump($dbname, $dumpfile) { 418a34ef333SKlap-in global $conf; 419a34ef333SKlap-in //backup existing stuff 420a34ef333SKlap-in $dbf = $conf['metadir'].'/'.$dbname; 421a34ef333SKlap-in $dbext = $this->adapter->getFileextension(); 422a34ef333SKlap-in $dbfile = $dbf.$dbext; 423a34ef333SKlap-in if(@file_exists($dbfile)) { 424a34ef333SKlap-in 425a34ef333SKlap-in $i = 0; 426a34ef333SKlap-in $backupdbfile = $dbfile; 427a34ef333SKlap-in do { 428a34ef333SKlap-in $i++; 429a34ef333SKlap-in $backupdbfile = $dbf.".copy$i".$dbext; 430a34ef333SKlap-in } while(@file_exists($backupdbfile)); 431a34ef333SKlap-in 432a34ef333SKlap-in io_rename($dbfile, $backupdbfile); 433a34ef333SKlap-in } 434a34ef333SKlap-in 435a34ef333SKlap-in $init = false; 436a34ef333SKlap-in if(!$this->adapter->initdb($dbname, $init, $sqliteupgrade = true)) { 437a34ef333SKlap-in msg('Initialize db fails'); 438a34ef333SKlap-in return false; 439a34ef333SKlap-in } 440a34ef333SKlap-in 441a34ef333SKlap-in $sql = io_readFile($dumpfile, false); 442a34ef333SKlap-in $sql = $this->SQLstring2array($sql); 443a34ef333SKlap-in 444a34ef333SKlap-in //skip preparing, because it interprets question marks as placeholders. 445a34ef333SKlap-in return $this->doTransaction($sql, $sqlpreparing = false); 446a34ef333SKlap-in } 447f10ea6c1SKlap-in 448a1e6784eSAndreas Gohr /** 4493ae3f79eSKlap-in * Registers a User Defined Function for use in SQL statements 4503ae3f79eSKlap-in */ 451aa81d781SKlap-in public function create_function($function_name, $callback, $num_args) { 452aa81d781SKlap-in $this->adapter->create_function($function_name, $callback, $num_args); 4533ae3f79eSKlap-in } 4543ae3f79eSKlap-in 4553ae3f79eSKlap-in /** 456a1e6784eSAndreas Gohr * Execute a query with the given parameters. 457a1e6784eSAndreas Gohr * 458a1e6784eSAndreas Gohr * Takes care of escaping 459a1e6784eSAndreas Gohr * 460a2a82480SAndreas Gohr * 461a2a82480SAndreas Gohr * @param string ...$args - the arguments of query(), the first is the sql and others are values 462aa81d781SKlap-in * @return bool|\SQLiteResult 463a1e6784eSAndreas Gohr */ 464aa81d781SKlap-in public function query() { 465a1e6784eSAndreas Gohr // get function arguments 466a1e6784eSAndreas Gohr $args = func_get_args(); 467a1e6784eSAndreas Gohr 468aa81d781SKlap-in return $this->adapter->query($args); 46987fa2c18Sstretchyboy } 470a1e6784eSAndreas Gohr 471a1e6784eSAndreas Gohr /** 472a1e6784eSAndreas Gohr * Join the given values and quote them for SQL insertion 473a1e6784eSAndreas Gohr */ 474aa81d781SKlap-in public function quote_and_join($vals, $sep = ',') { 475aa81d781SKlap-in return $this->adapter->quote_and_join($vals, $sep); 476a1e6784eSAndreas Gohr } 477a1e6784eSAndreas Gohr 478a1e6784eSAndreas Gohr /** 479a1e6784eSAndreas Gohr * Run sqlite_escape_string() on the given string and surround it 480a1e6784eSAndreas Gohr * with quotes 481a1e6784eSAndreas Gohr */ 482aa81d781SKlap-in public function quote_string($string) { 483aa81d781SKlap-in return $this->adapter->quote_string($string); 484a1e6784eSAndreas Gohr } 485a1e6784eSAndreas Gohr 486b5b947d7SAndreas Gohr /** 487fee3b689Sstretchyboy * Escape string for sql 488fee3b689Sstretchyboy */ 489aa81d781SKlap-in public function escape_string($str) { 490aa81d781SKlap-in return $this->adapter->escape_string($str); 491ff97cc8fSstretchyboy } 492ff97cc8fSstretchyboy 493ff97cc8fSstretchyboy /** 494b122d121SAndreas Gohr * Closes the result set (and it's cursors) 495b122d121SAndreas Gohr * 496b122d121SAndreas Gohr * If you're doing SELECT queries inside a TRANSACTION, be sure to call this 497b122d121SAndreas Gohr * function on all your results sets, before COMMITing the transaction. 498b122d121SAndreas Gohr * 4994b4b2db0SGerrit Uitslag * Also required when not all rows of a result are fetched 5004b4b2db0SGerrit Uitslag * 501b122d121SAndreas Gohr * @param $res 502b122d121SAndreas Gohr * @return bool 503b122d121SAndreas Gohr */ 504b122d121SAndreas Gohr public function res_close($res){ 505b122d121SAndreas Gohr return $this->adapter->res_close($res); 506b122d121SAndreas Gohr } 507b122d121SAndreas Gohr 508b122d121SAndreas Gohr /** 509aa81d781SKlap-in * Returns a complete result set as array 510ff97cc8fSstretchyboy */ 511ef383ac5SKlap-in public function res2arr($res, $assoc = true) { 512ef383ac5SKlap-in return $this->adapter->res2arr($res, $assoc); 513b5b947d7SAndreas Gohr } 514b5b947d7SAndreas Gohr 515b5b947d7SAndreas Gohr /** 516aa81d781SKlap-in * Return the wanted row from a given result set as 517aa81d781SKlap-in * associative array 518b5b947d7SAndreas Gohr */ 519aa81d781SKlap-in public function res2row($res, $rownum = 0) { 520aa81d781SKlap-in return $this->adapter->res2row($res, $rownum); 521b5b947d7SAndreas Gohr } 522b5b947d7SAndreas Gohr 523e7112ccbSAdrian Lang /** 52444685fc6SKlap-in * Return the first value from the next row. 525e7112ccbSAdrian Lang */ 526aa81d781SKlap-in public function res2single($res) { 527aa81d781SKlap-in return $this->adapter->res2single($res); 528e7112ccbSAdrian Lang } 529fee3b689Sstretchyboy 530fee3b689Sstretchyboy /** 531fee3b689Sstretchyboy * fetch the next row as zero indexed array 532fee3b689Sstretchyboy */ 533aa81d781SKlap-in public function res_fetch_array($res) { 534aa81d781SKlap-in return $this->adapter->res_fetch_array($res); 53587fa2c18Sstretchyboy } 536fee3b689Sstretchyboy 537fee3b689Sstretchyboy /** 538fee3b689Sstretchyboy * fetch the next row as assocative array 539fee3b689Sstretchyboy */ 540aa81d781SKlap-in public function res_fetch_assoc($res) { 541aa81d781SKlap-in return $this->adapter->res_fetch_assoc($res); 542fee3b689Sstretchyboy } 543fee3b689Sstretchyboy 544fee3b689Sstretchyboy /** 54578977d74SKlap-in * Count the number of records in result 5463157674bSAndreas Gohr * 547db58e525SKlap-in * This function is really inperformant in PDO and should be avoided! 548fee3b689Sstretchyboy */ 549aa81d781SKlap-in public function res2count($res) { 550aa81d781SKlap-in return $this->adapter->res2count($res); 551fee3b689Sstretchyboy } 55224a03f6cSstretchyboy 55324a03f6cSstretchyboy /** 55424a03f6cSstretchyboy * Count the number of records changed last time 55524a03f6cSstretchyboy */ 55644685fc6SKlap-in public function countChanges($res) { 55744685fc6SKlap-in return $this->adapter->countChanges($res); 558a1e6784eSAndreas Gohr } 559a1e6784eSAndreas Gohr 560aa81d781SKlap-in} 561