PHP Classes
Icontem

File: as_dbutils.php


  Search   All class groups All class groups   Latest entries Latest entries   Top 10 charts Top 10 charts   Newsletter Newsletter   Blog Blog   Forums Forums   Help FAQ Help FAQ  
  Login   Register  
Recommend this page to a friend! ReTweet ReTweet Stumble It! Stumble It! Bookmark in del.icio.us Bookmark in del.icio.us
  Classes of Alexander Selifonov  >  site administrator tool set  >  as_dbutils.php  
File: as_dbutils.php
Role: Class source
Content type: text/plain
Description: Database access wrapper class
Class: site administrator tool set
Web interface to manage site resources
 

Contents

Class file image Download
<?php
/**
 *********************************************************************
 @package: as_dbutils.php
 @desc    SQL data accessing wrapper with backup/restore functions
 @author: Alexander Selifonov <as-works@narod.ru>
 @link http://as-works.narod.ru
 last_modified (mm.dd.yyyy): 14.04.2008
 @version: 0.98.127
 *********************************************************************
**/
define('DBTYPE_MYSQL',1);
define('XML_PREFIX', 'AS_table'); # root tag in backup xml-file
define('DB_DEFAULTCHARSET','WINDOWS-1251');
$findcnt = 0;
/**
* if var $as_dbparam('server'=>'hostaddr', 'dbname'=>'mybase','username'=>'login','password'=>'psw') set,
* connection will be created inside this class, and passing these vars to constructor is not nessesary
*/
class CDbEngine { // main class def.
  var $dbtype = DBTYPE_MYSQL;
  var $host = '';
  var $username = '';
  var $password = '';
  var $db_name = '';
  var $b_permconn = true; # use permanent connection when possible
  var $connection = false;
  var $connected = false;
  var $qrylink = 0; # link returned by  last sql_query()
  var $affectedrows = 0;
  var $lastquerytext = ''; # last executed query text
  var $tables = array(); # table list for backup
  var $outputfile = ''; # output backup filename
  var $fhan = 0; # file handle for backup file read/write
  var $bckp_emptyfields = 0; // 1 or true - backup with empty (default) field values
  var $charset = DB_DEFAULTCHARSET;
  var $rfrom = array("\\",'<','>');
  var $rto = array("\\x92","\\x60","\\x62");
  var $gzmode = false;
  var $verbose = 0;
  var $buf = '';
  var $tmpbuf = '';
  var $stoptag = '';
  var $fileeof = false;
  var $errormessage = '';
  var $errorlog_file = '';
  var $extract_ddl = true; // put 'CREATE TABLE...' operators into backup file
  var $tablename = '';
  var $createSql = '';
  var $bContents = false; // create table-list in backup XML file
  var $emulate = false; // restore,sql_query: no real INSERT, just emulating (debug or other purposes)
  var $logging = false; # logging mode (0-don't log anything)
  var $safemode = 1; # converting 'unsafe' chars in text fields method : 0:no conversion, 1:'=>", 2:addslashes()
  var $blobfields = array(); # these fields excluded from "str_replace" before update
  var $bckp_filter=array(); # $bckp_filter['mytable']= "datecreate='2006-12-31'" - backup records filter
  function CDbEngine($db_type=DBTYPE_MYSQL, $host=false,$user=false,$password=false,$dbname=false) {
    global $as_dbparam;
    $this->dbtype=$db_type;
    if($host===false && isset($as_dbparam['server']))       $host = $as_dbparam['server'];
    if($user===false && isset($as_dbparam['username']))     $user = $as_dbparam['username'];
    if($password===false && isset($as_dbparam['password'])) $password = $as_dbparam['password'];
    if($dbname===false   && isset($as_dbparam['dbname']))   $dbname   = $as_dbparam['dbname'];
    # some providers ban persistent connections, so just define this CONST to force using mysql_connect()
    if(defined('DB_AVOID_PERSISTENT_CONNECT')) {
      $this->b_permconn = false;
    }
    if($host!==false) $this->Connect($host,$user,$password,$dbname);
  }
  /**
  * @desc sets list of filed names that are 'BLOB', so do not convert them with addslashes or str_replace
  */
  function SetBlobFields($fldarray) {
    if(is_string($fldarray)) $this->blobfields = split("[,;|]",$fldarray);
    elseif(is_array($fldarray)) $this->blobfields = $fldarray;
  }
  function SaveDDLMode($flag=true) { $this->extract_ddl = $flag; }
  function SetCharSet($charset) { $this->charset = strtoupper($charset); }

  function AddBackupFilter($prm1,$prm2) { // add an array or one filter
    if(is_array($prm1)) $this->bckp_filter = array_merge($this->bckp_filter,$prm1);
    else $this->bckp_filter[$prm1]= $prm2;
  }

  function SetVerbose($flag=true) { $this->verbose = $flag; }
  function GetErrorMessage() { return $this->errormessage; }
  function Connect($host=false,$user=false,$password=false,$dbname=false) {
    $b_reconnect= false;
    if(!$this->connected) {
      if($host!==false) $this->host = $host;
      if($user!==false) $this->username = $user;
      if($password!==false) $this->password = $password;
      $b_reconnect = true;
    }
    $ret = false;
    switch($this->dbtype) {
    case DBTYPE_MYSQL:
      $ret = ($b_reconnect? (($this->b_permconn)? @mysql_pconnect($this->host,$this->username,$this->password) :
      @mysql_connect($this->host,$this->username,$this->password)) : true);
      if($this->logging) {
        $flog = fopen('as_dbutils.log','a');
        if($flog) {
          fwrite($flog, "\n".date('Y-m-d H:i:s')."|opening DB, server=[{$this->host}], db=[$dbname/$this->db_name]");
          fclose($flog);
        }
      }

      if($ret) {
        if($b_reconnect) $this->connection = $ret;
        if(!empty($dbname)) $this->db_name = $dbname;
        $ret = mysql_select_db($this->db_name);
        if(!is_resource($ret)) $this->errormessage = mysql_error();
      }
      else {
        $ret = false;
        if(function_exists('WriteDebugInfo')) WriteDebugInfo("as_dbutils- ERROR connecting, host={$this->host}, user={$this->username}, pwd={$this->password}",mysql_error());
      }
      $this->errormessage = mysql_error();
      break;
      // case other DBTYPE_...
    }
    $this->connected = $ret;
    #echo "debug: CDEngine::Connect done: $ret<br>"; #debug
    return $ret;
  }
  function select_db($dbname) {
    $ret = false;
    switch($this->dbtype) {
    case DBTYPE_MYSQL:
      $ret = mysql_select_db($dbname);
      if($ret) $this->db_name = $dbname;
      $this->errormessage = mysql_error();
      break;
      // case other DBTYPE_...
    }
    return $ret;
  }
  function GetDbVersion() {
    # works for MySQL only for the moment
    $lnk = $this->sql_query('SELECT VERSION()');
    $ret = '';
    if(is_resource($lnk) && ($r=$this->fetch_row($lnk))) {
      $ret = $r[0];
      $this->free_result($lnk);
    }
    return $ret;
  }

  function Disconnect() {
    switch($this->dbtype) {
    case DBTYPE_MYSQL:
      if(empty($this->b_permconn)) mysql_close($this->connection);
      $connected = false;
      return true;
#   case other DBTYPE_...
    }
    return false;
  }
  # GetTableList() - returns array with all table names
  function GetTableList() {
    $ret = array();
    switch($this->dbtype) {
    case DBTYPE_MYSQL:
      $tlnk = mysql_query('show tables');
      while($tlnk && ($trow = mysql_fetch_row($tlnk))) { $ret[] = $trow[0]; }
      break;
    # case DBTYPE_...
    }
    return $ret;
  }
  function GetFieldList($tablename) {
    $lnk = $this->sql_query("DESC $tablename");
    $ret = array();
    while(is_resource($lnk) && ($r=$this->fetch_row($lnk))) $ret[] = $r;
    if(is_resource($lnk)) $this->free_result($lnk);
    return $ret;
  }
  function affected_rows() {
    switch($this->dbtype) {
    case DBTYPE_MYSQL:
      $ret = mysql_affected_rows(); break;
    # case DBTYPE_...
    }
    return $ret;
  }
  function insert_id() {
    switch($this->dbtype) {
    case DBTYPE_MYSQL: return mysql_insert_id();
    # case DBTYPE_...
    }
    return $ret;
  }
  function sql_errno() {
    switch($this->dbtype) {
    case DBTYPE_MYSQL: return mysql_errno();
    # case DBTYPE_...
    }
    return 0;
  }
  function sql_error() {
    switch($this->dbtype) {
    case DBTYPE_MYSQL: return mysql_error();
    # case DBTYPE_...
    }
    return 0;
  }
  function IsTableExist($table) {
    switch($this->dbtype) {
    case DBTYPE_MYSQL:
      $ret = (mysql_query("SELECT COUNT(*) FROM $table"))? true:false;
      break;
    }
    return $ret;
  }
  function sql_query($query,$getresult=false, $assoc=false) { // universal query execute
    $this->lastquerytext = $query;
    $this->affectedrows = 0;
    if($this->emulate && strtoupper(substr($query,0,6))!='SELECT') {
      echo "emulate query: $query\r\n<br />";
      $ret = $this->affectedrows = 0;
      return $ret;
    }
    switch($this->dbtype) {
    case DBTYPE_MYSQL:
      $ret = $this->qrylink = mysql_query($query);
      $this->affectedrows = ($ret? mysql_affected_rows() : false);
      $this->errormessage = mysql_error();
      break;
    # case DBTYPE_...
    }
    if($this->affectedrows>0 && !empty($getresult)) {
       $ret = ($assoc)? $this->fetch_assoc($this->qrylink) : $this->fetch_row($this->qrylink);
    }
    if($this->logging) {
      $flog = fopen('as_dbutils.log','a');
      if($flog) {
        fwrite($flog, "\n".date('Y-m-d H:i:s')."|exec query|$query|{$this->qrylink}|err:{$this->errormessage}|rows: {$this->affectedrows}");
        fclose($flog);
      }
    }
    if(strlen($this->errormessage) && strlen($this->errorlog_file)) {
       $flog = fopen($this->errorlog_file,'a');
       if($flog) {
         fwrite($flog,date('Y-m-d H:i:s')." : SQL: $query; Error: {$this->errormessage}\n");
         fclose($flog);
       }
    }
    return $ret;
  }

  function sql_explain($query) { // 'explain plan'
    $this->lastquerytext = $query;
    $this->affectedrows = 0;
    switch($this->dbtype) {
    case DBTYPE_MYSQL:
      $ret = $this->qrylink = mysql_query("EXPLAIN $query");
      $this->affectedrows = ($ret? mysql_affected_rows() : false);
      $this->errormessage = mysql_error();
      break;
    # case DBTYPE_...
    }
    return $ret;
  }

  function fetch_row($link) {
    if(!is_resource($link)) return false;
    switch($this->dbtype) {
    case DBTYPE_MYSQL:
      $ret = mysql_fetch_row($link);
      if(mysql_error()) echo "as_dbutils:fetch_row: wrong link $link !";
      return $ret;
      break;
    # case DBTYPE_...
    }
    return false;
  }
  function fetch_assoc($link) {
    switch($this->dbtype) {
    case DBTYPE_MYSQL: return mysql_fetch_assoc($link);
    # case DBTYPE_...
    }
    return false;
  }
  function fetch_object($link) {
    switch($this->dbtype) {
    case DBTYPE_MYSQL: return mysql_fetch_object($link);
    # case DBTYPE_...
    }
    return false;
  }

  function SQLBuildAndExecute($table,$sqltype,$p1='',$p2='',$p3=false,$p4=false) {
  # builds SQL query and execute it. Returns cursor link or false, $this->affectedrows holds affected rows count
    $ret = false;
    $qry = '';
    $sqltype = strtoupper($sqltype);
    switch($sqltype) { #<3>
      case 'S': case 'SELECT': # $table-table(s), p2-field(s) to select, $p3- WHERE conditions
        $qry = "SELECT $p1 FROM $table";
        if(is_string($p2) && !empty($p2) ) {
          if($p3===false) // WHERE condition in p3, so don't build filed=value
               $cond = $p2;
          else $cond = "$p2='$p3'";
          $qry .= " $cond";
        }
        break;
      case 'I': case 'INSERT': # $table-table, $p1-'field'=>value assoc.array
        $flist = $vlist = '';
        foreach($p1 as $fld=>$value) {
          $flist .= ($flist==''?'':',').$fld;
          if($value==='now') $oneval = 'SYSDATE()';
          else {
            $oneval = "'";
            if($this->safemode==0 || in_array($fld,$this->blobfields)) $oneval .= $value;
            elseif($this->safemode==1) $oneval .= str_replace("'",'"',$value);
            else $oneval .= addslashes($value);
            $oneval .= "'";
          }
          $vlist .= ($vlist==''?'':',').$oneval;
        }
        $qry = "INSERT INTO $table ($flist) VALUES ($vlist)";
        break;
      case 'U': case 'UPDATE': # $table-table, $p1-'field'=>value assoc.array, $p2,$p3= PK field name and it's value
        $flist='';
        foreach($p1 as $fld=>$value) {
          if($value==='now') $oneval = 'SYSDATE()';
          else $oneval = "'". str_replace("'",'"',$value). "'"; // SQL injection protect! (TODO!)
          $flist .= ($flist==''?'':',')."$fld=$oneval";
        }
        $qry = "UPDATE $table SET $flist";
        $cond = '';
        if(is_string($p2) && !empty($p2) ) {
          if($p3===false) // WHERE condition in p3, so don't build filed=value
               $cond = $p2;
          else $cond = "$p2='$p3'";
        }
        if($cond!='') $qry .= " WHERE $cond";
        else $qry = ''; # protect from accident WHOLE TABLE update
        break;
      case 'D': case 'DELETE': # p1 - WHERE condition ("field=value" or what else...
        if(!empty($p1)) $qry = "DELETE FROM $table WHERE $p1";
        break;
    } #<3> switch end
    if($qry !='')  $ret = $this->sql_query($qry);
#    echo "SQLBuildAndExecute qry: $qry, result: $ret, error:<br>".$this->sql_error(); #debug
    return $ret;
  }

  function free_result($link) {
    switch($this->dbtype) {
    case DBTYPE_MYSQL:
      if(is_resource($link)) mysql_free_result($link);
      break;
    # case DBTYPE_...
    }
  }
  /**
  * @desc returns record count for desired table (with optional WHERE condition, if passed)
  */
  function GetRecordCount($tblname,$filter='') {
#    $flt = '(1)'.(empty($filter)? '':" AND $filter");
    $result = $this->GetQueryResult($tblname,'COUNT(1)',$filter);
    return $result;
  }
  function GetQueryResult($table,$fieldlist,$cond='',$multirow=false, $assoc=false,$safe=false) {
    $qry="SELECT $fieldlist FROM $table". ($cond==''? '': " WHERE $cond");
    $lnk = $this->sql_query($qry);
#    echo "$qry ".mysql_error(); #debug
    if(empty($lnk)) return false;
    $reta = false;
    while(($row=($assoc ? $this->fetch_assoc($lnk): $this->fetch_row($lnk) ))) {
      if($safe && !get_magic_quotes_runtime()) {
        foreach($row as $key=>$val) $row[$key] = addslashes($val);
      }
      if(($assoc)) $retvalue = $row;
      else $retvalue = (count($row)==1) ? $row[0] : $row;
      if(empty($multirow)) return $retvalue;
      if(!is_array($reta)) $reta=array();
      $reta[] = $retvalue;
    }
    $this->free_result($lnk);
    return $reta;
  }
  function SqlAffectedRows() { return $this->affectedrows; }
  function FileWrite($strg) {
    return (($this->gzmode)? gzwrite($this->fhan,$strg):fwrite($this->fhan,$strg));
  }
  /**
  * @desc CloneRecords() duplicates record(s) in the table
  * @param $atblename - table name
  * @param $pk_name - primary key field name
  * @param $pk_value - one value or value array of records to be cloned
  */
  function CloneRecords($tablename,$pk_name,$pk_value,$desttable='') {
    $ret = 0;
    $totable = ($desttable=='')? $tablename:$desttable;
    if(is_array($pk_value)) {
      $ret = array();
      foreach($pk_value as $val) {
        $dta = $this->GetQueryResult($tablename,'*',"$pk_name='$val'",false,true,true);
        if($totable==$tablename) unset($dta[$pk_name]);
        $this->SQLBuildAndExecute($totable,'I',$dta);
        if($this->affected_rows())  $ret[] = $this->insert_id();
      }
    }
    else {
      $dta = $this->GetQueryResult($tablename,'*',"$pk_name='$pk_value'",false,true);
      if($totable==$tablename) unset($dta[$pk_name]);
      $this->SQLBuildAndExecute($totable,'I',$dta);
      if($this->affected_rows()) $ret = $this->insert_id();
    }
    return $ret;
  }
  function GetTableStructure($table) {
    $qry = 'DESC '.$table;
    $rsrc = $this->sql_query($qry);
    $ret = array();
    switch($this->dbtype) {
    case DBTYPE_MYSQL:;
      while(($row=$this->fetch_row($rsrc))) {
       //  $ret[field_name] =[ type,  Null ,   Key(MUL|PRI) Default Extra (auto-increment)
       $ret[$row[0]] = array($row[1], $row[2],$row[3],$row[4],$row[5]);
      }
      break;
    # case DBTYPE_...
    }
    return $ret;
  }

  // backup/restore data function
  function TryOpenBackupFile($fname) {
     if($this->fhan>0) $this->fileClose();
     $flen = strlen($fname);
     if($flen<1) return false;
     $this->gzmode = ($flen>3 && strtolower(substr($fname,$flen-3))=='.gz')? 1:0;
     $this->fileeof = false;
     $this->fhan = ($this->gzmode? @gzopen($fname,'r') : @fopen($fname,'r'));
     if(empty($this->fhan)) {
       $this->errormessage = 'Cannot open backup file '.$fname;
       return false;
     }
     $this->buf = ''; $this->tempbuf = '';
     $result = $this->FindStartTag(XML_PREFIX);
     return true;
  }
  function FileClose() {
    $closed = ($this->gzmode? gzclose($this->fhan): fclose($this->fhan));
    $this->fhan = 0;
  }
  function FileRewind() {
    if($this->gzmode) gzrewind($this->fhan);
    else  rewind($this->fhan);
  }
  function CreateContents($var=true) { $this->bContents = $var; }
  function BackupOneTable($tablename) {
    $defval = array();
    $ret = 0;
    if(empty($this->bckp_emptyfields)) { # get default fields values into $defval
      $defval = $this->GetTableStructure($tablename);
    }
    if(is_array($defval)) { #<2>
     $this->FileWrite(" <as_dbutils_table><name>$tablename</name>\n");
     if($this->extract_ddl) { #<3>
       $lnk = mysql_query("SHOW CREATE TABLE $tablename");
       if(is_resource($lnk) && ($r=mysql_fetch_row($lnk))) { #<4>
          $ddl = $r[1];
          $this->FileWrite(" <CreateSQL>$ddl</CreateSQL>\n");
       } #<4>
     } #<3>
    } #<2>
    $qry = "SELECT * FROM $tablename".(empty($this->bckp_filter[$tablename])?'':' WHERE '.$this->bckp_filter[$tablename]);
    $lnk = $this->sql_query($qry);
    if(is_resource($lnk)) {
      $rcnt = 0;
      while(($lnk) && ($r=$this->fetch_assoc($lnk))) {
        $this->FileWrite("  <as_dbutils_record>\n");
        while (list($key, $val) = each($r)) { //<3>
         if($this->bckp_emptyfields || $val !=$defval[$key][3] ) {
           $val = str_replace($this->rfrom, $this->rto, $val);
           $this->FileWrite("   <$key>$val</$key>\n");
         }
        } //<3>
        $rcnt++;
        $this->FileWrite("  </as_dbutils_record>\n");
      }
      $this->FileWrite(" </as_dbutils_table>\n");
      if($this->verbose) echo date('Y.m.d H:i:s')." &nbsp;$tablename, records saved: $rcnt<br>\n";
      $ret = 1;
    }
    else {
      if($this->verbose) echo date('Y.m.d H:i:s')." &nbsp;table $tablename does not exist !<br>\n";
    }
    return $ret;;
  }

  function BckpBackupTables($tlist, $fname='', $pack=0) {
    $this->tables = $tlist;
    if(!is_array($this->tables) || count($this->tables)<1)
      $this->tables = $this->GetAllTablesList();
    if(count($this->tables)<1) { $this->errormessage = "Empty table list or no connection"; return 0; }
    $this->gzmode = (($pack) && function_exists('gzopen'));
    if($fname==='') $fname = 'backup-'.date('Y-m-d').'.xml';
    if(!is_array($this->tables) || count($this->tables)<1) return false;

    $this->outputfile = $fname .($this->gzmode ? '.gz':'');
    $this->fhan = ($this->gzmode)? @gzopen($this->outputfile, 'w9') : @fopen($this->outputfile,'w');
    if(empty($this->fhan)) { $this->errormessage='Cannot open output file for writing'; return 0; }
    $this->FileWrite("<?xml version=\"1.0\" encoding=\"$this->charset\"?>\n");
    $this->FileWrite('<'.XML_PREFIX.">\n");
    $retcode = 0;
    if($this->bContents) {
        $stlist = '';
        foreach($this->tables as $tname) $stlist .= ($stlist=='' ? '':',').$tname;
        $this->FileWrite("<TableList>$stlist</TableList>\n");
    }
    reset($this->tables);
    foreach($this->tables as $tname) {
       $retcode += $this->BackupOneTable($tname);
    }
    $this->FileWrite('</'.XML_PREFIX.">\n");
    $this->FileClose();
    return $retcode;
  } // BackupTables() end

  function GetAllTablesList() {
    $ret = array();
    switch($this->dbtype) {
    case DBTYPE_MYSQL:
      $lnk=$this->sql_query('SHOW TABLES');
      if($this->affected_rows()<1) { $this->errormessage = "no tables in DB or no DB connection"; return 0; }
      while(($tbl=mysql_fetch_row($lnk))) { $ret[] = $tbl[0]; }
      break;
#   case DBTYPE_xxx ...
    }
  }
  function BackupDatabase($fname='',$pack=0) {
    $tlist = $this->GetAllTablesList();
    if(is_array($tlist) && count($tlist))
      $this->BackupTables($tlist, $fname, $pack);
  }

  function ReadFilePortion($bytes=4096) {
       if(!$this->fileeof && !empty($this->fhan)) {
         $this->buf .= $this->gzmode ? gzread($this->fhan,$bytes): fread($this->fhan,$bytes);
         $this->fileeof = $this->gzmode ? gzeof($this->fhan) : feof($this->fhan);
#         echo "<br>read file portion $bytes ...<br>"; // debug
       }
       return $this->fileeof;
  }

  function FindStartTag($tag, $dropoldbuf=false,$maxbytes=0) {
    global $findcnt;
    $ftag = "<$tag>";
    $readcount=0;
    while(1) {
#      $findcnt++; if($findcnt>20) break;
      if(($npos = strpos($this->buf,$ftag))!==false) {
        if($this->stoptag !=='') { //<4>
           $endpos = strpos($this->buf,'<'.$this->stoptag.'>');
           if($endpos !==false && $endpos < $npos) return -1;
        } //<4>
        if($dropoldbuf) { $this->buf = substr($this->buf, $npos); $npos = 0; }
        return $npos;
      }
      if($this->fileeof || (!empty($maxbytes) && $readcount>=$maxbytes)) break;
      $this->ReadFilePortion(); $readcount += 4096;
#      echo "debug FindStartTag($tag): read 4096<br>"; # debug
    }
    return -1; // no more tags in stream!
  }

  function FindEndTag($tag, $stoptag='', $dropoldbuf=false ) {
    $ftag = "</$tag>";
    while(1) {
      if(($npos = strpos($this->buf,$ftag))!==false) {
        if($dropoldbuf) { $this->buf = substr($this->buf, $npos); $npos = 0; }
        return $npos;
      }
      if(!$this->fileeof) $this->ReadFilePortion();
      else break;
    }
    return -1; // no more tags in stream!
  }

  function FindXmlValue($tag,$maxbytes=0) { // read from <tag> to </tag> into result
     $ret = false;
     $taglen = strlen($tag);
     $pos2 = $this->FindStartTag($tag,1,$maxbytes);
     if($pos2>=0) {
        $pos3 = $this->FindEndTag($tag);
        if($pos3>0) {
             $ret = substr($this->buf,$pos2+$taglen+2,$pos3-$pos2-$taglen-2);
             $this->buf = substr($this->buf,$pos3+$taglen+3);
        }
     }
     return $ret;
  }

  function GetNextTable() { // finds <table> beginning, read CREATE TABLE DDL
     $strt = $this->FindStartTag('as_dbutils_table',1);
     $ret = 0;
     if($strt>=0) {
        $this->tablename = $this->FindXmlValue('name');
        $this->createSql = '';
        if(strpos($this->buf, '<CreateSQL>')!==false) {
           $this->createSql = $this->FindXmlValue('CreateSQL');
        }
        $ret = 1;
     }
     return $ret;
  }
  function BuildInsertSql($xmlrecord) {
    $ret = '';
    $flds = array();
    while(1) {
       $spos1 = strpos($xmlrecord,'<');
       if($spos1!==false) {
          $spos2 = strpos($xmlrecord,'>',$spos1+1);
          if($spos2!==false) {
            $fldname = substr($xmlrecord,$spos1+1, $spos2-$spos1-1);
            $spos3 = strpos($xmlrecord,"</$fldname>",$spos2+1);
            if($spos3> $spos2) { //<6>
              $fvalue = substr($xmlrecord,$spos2+1,$spos3-$spos2-1);
              $flds[$fldname]=addslashes($fvalue); // escape special chars!
              $xmlrecord = substr($xmlrecord, $spos3+strlen($fldname)+2);
            } //<6>
          }
          else break;
       }
       else break;
    }
    if(count($flds)) {
      // building SQL INSERT into...
      $fnames = ''; $fvals = '';
      reset($flds);
      foreach ($flds as $fldname => $fvalue) {
        $fnames .= ($fnames==''?'':',').$fldname;
        $fvalue = str_replace($this->rto, $this->rfrom, $fvalue); // decode spec chars
        $fvals .= ($fvals==''?'':',')."'$fvalue'";
      }

      $ret = "INSERT INTO {$this->tablename} ($fnames) VALUES ($fvals)";
    }
    return $ret;
  }
  function BckpGetContents($fname) { // gets table list from XML backup file
     if(empty($fname)) return '';
     $this->TryOpenBackupFile($fname);
     if(empty($this->fhan)) return 0;
     $ret = array();
     $slist = $this->FindXmlValue('TableList',4096);
     if(strlen($slist)>0) { // contents (table list) exist, so get it!
       $ret = explode(',',$slist);
#       echo "debug:GetContents short way!";
     }
     else { // long way - get all table names by GetNextTable()
#       echo "debug:GetContents LONG way!<br>";
       $this->FileRewind();
#       $ideb = 0;
       while(($this->GetNextTable())) {
         $ret[] = $this->tablename;
#         $ideb++; if($ideb>=100) break;
       }
     }
     $this->FileClose();
     return $ret;
  }
  /**
  * @desc BckpRestoreTables() restores SQL data from xml[.gz] backup file.
  * @param $fname - backup filename to restore from
  * @param $verbose - if not empty, function echoes log
  * @param $tlist - can be table names array  that must be restored (the rest will be skipped)
  */
  function BckpRestoreTables($fname, $verbose=0, $tlist='') {
     $flen = strlen($fname);
     $this->verbose = $verbose;
     $this->TryOpenBackupFile($fname);
     if(empty($this->fhan)) return false;

     if($this->verbose && $this->emulate) echo "Emulated Restore, no real data changing...<br>\n";
     if($this->verbose) echo date('Y.m.d H:i:s')." Restore from $fname begin <hr>\n";
     $ret = 0;
     while(1) { //<3>
        $result = $this->GetNextTable();
        if($result) { //<4>
          $inscnt = $errcnt = 0;
          $ret++;
          $skiptable = (is_array($tlist) && !in_array($this->tablename,$tlist));
          if($skiptable) {
            if($this->verbose) echo $this->tablename." - skipped<br />\n";
            continue;
          }
          $this->stoptag = '/as_dbutils_table'; // don't miss table end!
          if($this->createSql !=='') { //<5>
            $qry = 'DROP TABLE '.$this->tablename;
            if($this->verbose) echo date('Y.m.d H:i:s')." {$this->tablename} : Re-creating table...<br>";
            if(empty($this->emulate)) { //<6>
              mysql_query($qry);
              $created = mysql_query($this->createSql);
              if(empty($created)) { //<7>
                $this->errormessage = "{$this->tablename}: Re-creating table error: ".mysql_error();
                if($this->verbose) echo "{$this->errormessage}<br>\n";
                return 0;
              } //<7>
            } //<6>

          } //<5>
          else { // no CREATE DDL, so just truncate table before adding records
            if($this->verbose) echo date('Y.m.d H:i:s')."$this->tablename : truncating before adding data...<br>";
            if(empty($this->emulate)) $this->sql_query('TRUNCATE TABLE '.$this->tablename);
          }

          // start parse records and inserting thrm into the table
          while(($record = $this->FindXmlValue('as_dbutils_record'))) {
            $sql = $this->BuildInsertSql($record);
//            if($this->verbose) echo "  &nbsp; inserting record: $sql<br>";
            $this->sql_query($sql);
            if($this->errormessage) $errcnt++;
            else $inscnt++;
          }
          if($this->verbose) echo date('Y.m.d H:i:s')." $this->tablename, inserted records: $inscnt, failed inserts: $errcnt<br>";
          $epos = $this->FindEndTag('as_dbutils_table');
          if($epos !== false) $this->buf = substr($this->buf, $epos+18);
        } //<4>
        else { // no more tables in backup file
          break;
        }
     } //<3> while read loop
     if($this->verbose) echo date('Y.m.d H:i:s')."<hr> Restore from $fname finished<br>";
     $this->FileClose();
     return $ret;
  } // BackupTables() end

} // CDbEngine definition end

/**
* @desc cleanup OnExit - closes db connection
*/
function As_dbutilsCleanUp() {
  @mysql_close();
#  if(function_exists('WriteDebugInfo')) WriteDebugInfo("as_dbutils cleanup code done (closing Mysql connection)");
}
if(defined('DB_AVOID_PERSISTENT_CONNECT')) register_shutdown_function('As_dbutilsCleanUp');

$as_dbengine = new CDbEngine(); // ready-to-use class instance
?>

 
  Advertise on this site Advertise on this site   Site map Site map   Statistics Statistics   Site tips Site tips   Privacy policy Privacy policy   Contact Contact  

For more information send a message to :
info at phpclasses dot org.
Copyright (c) Icontem 1999-2009 PHP Classes - PHP Class Scripts
  PHP Book Reviews - Reviews of books and other products