<?php
/**
 *=========================================================
 *
 * @author     hahawen(大龄青年)  <[email protected]>
 * @since      2004-09-16
 * @copyright  Copyright (c) 2004, NxCoder Group
 *
 *=========================================================
 *
 * This file is part of SmartWeb code.
 *
 * SmartWeb is a MVC framework, base on Php5.0 and leter.
 * It's made by a class tree that meet the methed of OOP,
 * use a few xml file to config the web site,
 * and use template tech parse html file.
 *
 *  SmartWeb can be seen as Php Enterprise Solution.
 *
 * you can free redistribute it and/or modify it,
 * but please remain these license
 *=========================================================
 */
/**
 * class Db_Mysqli
 * use mysqli package access mysql database
 * access warning and error throw Exception to up_level class
 *
 * @package SmartWeb.common
 * @version 1.0
 */
class DB_Mysqli{

/**
 * mysql host location
 * @var stirng
 * @access private
 */
private $dbHost = '';
/**
 * mysql database name
 * @var stirng
 * @access private
 */
private $dbName = '';
/**
 * mysql username
 * @var stirng
 * @access private
 */
private $dbUser = '';
/**
 * mysql user password
 * @var stirng
 * @access private
 */
private $dbPassword = '';
/**
 * mysql connection
 * @var mysqli
 * @access private
 */
private $mysqli;
/**
 * construct function
 * @param string $host        mysql host location
 * @param string $user        mysql username
 * @param string $password    mysql user password
 * @param string $db          mysql database name
 * @access public
 */
public function __construct($host, $user, $password, $db){
$this->dbHost = $host;
$this->dbUser = $user;
$this->dbPassword = $password;
$this->dbName = $db;
$this->mysqli = new mysqli($this->dbHost, $this->dbUser, $this->dbPassword, $this->dbName);
}
    /**
     * execute UPDATE/INSERT/DELETE sql
     * @access public
     * @param  string $sql   query string
     * @return int|RuntimeException 
     */
public function execute($sql){
$result = $this->mysqli->execute($sql);
if($this->mysqli->errno)
throw new RuntimeException("{$this->mysqli->errno}--{$this->mysqli->error}");
return $mysqli->effected_rows();
}
    /**
     * get ResultSet of the select result
     * @access public
     * @param  string $sql   query string
     * @return ResultSet|RuntimeException 
     */
public function query($sql){
$result = $this->mysqli->query($sql);
if($this->mysqli->errno)
throw new RuntimeException("{$this->mysqli->errno}--{$this->mysqli->error}");
while($row = $result->fetch_assoc())
$data[] = $row;
return $data;
}
    /**
     * get first row and first column value of the select result
     * @access public
     * @param  string $sql    query string
     * @param  string $field  column name of return data
     * @return mix|null 
     * @see    self::query()
     */
public function getOne($sql, $field){
$result = $this->query($sql);
if(sizeof($result)>0)
return $result[0][$field];
else
return null;
}
    /**
     * get first row of the select result
     * @access public
     * @param  string $sql   query string
     * @return array|null 
     * @see    self::query()
     */
public function getRow($sql){
$result = $this->query($sql.' LIMIT 0,1');
if(sizeof($result)>0)
return $result[0];
else
return null;
}
    /**
     * page query function
     *
     * @access public
     * @param  string  $sql        sql
     * @param  int     $page       current query page number, form 1 to n
     * @param  int     $pageSize   number show in one page
     * @return array
     * result as blow:
     *             array('pageSize'    => number show in one page
     *                  'recordCount' => total records
     *                  'pageCount'   => total pages
     *                  'page'        => current page
     *                  'isFirst'     => is first page?
     *                  'isLast'      => is last page?
     *                  'start'       => result form record Id
     *                  'end'         => result to record Id
     *                  'sql'         => sql
     *                  'data'        => result array
     *                 )
     
     * @see    self::query()
     */
    public function pageQuery($sql, $page=1, $pageSize=20){
     $countSql = preg_replace('|SELECT.*FROM|i','SELECT COUNT(*) count FROM', $sql);
    
     $count = $this->getOne($countSql, 'count');
     $page = (int)$page<1? 1: (int)$page;
     $pageSize = (int)$pageSize<1? 20: (int)$pageSize;
    
        $data['recordCount'] = $count;
        $data['pageSize'] = $pageSize;
        $data['pageCount'] = ceil($data['recordCount']/$data['pageSize']);
        $data['page'] = $page>$data['pageCount']? $data['pageCount']: $page;
        $data['isFirst'] = $data['page']>1? false: true;
        $data['isLast'] = $data['page']<$data['pageCount']? false: true;
        $data['start'] = ($data['page']==0)? 0: ($data['page']-1)*$data['pageSize']+1;
        $data['end'] = ($data['start']+$data['pageSize']-1);
        $data['end'] = $data['end']>$data['recordCount']? $data['recordCount']: $data['end'];
        $data['sql'] = $sql.' LIMIT '.($data['start']-1).','.$data['pageSize'];
        
        $data['data'] = $this->query($data['sql']); 
        
        return $data;
    }
    /**
     * get last database operation affected rows
     * @access public
     * @return int 
     */    
    public function getAffectedRows(){
     return $this->mysqli->affected_rows();
    }
    /**
     * get last insert id
     * @access public
     * @return int 
     */
    public function getInsertId(){
        return $this->mysqli->insert_id;
    }
    /**
     * get sequence, need a sequence table to save sequence statistic
     * table defined blow:
     *
     * CREATE TABLE $table (
 *    seq_name VARCHAR( 20 ) NOT NULL ,
 *    seq_num BIGINT( 20 ) DEFAULT 1 NOT NULL ,
 *    PRIMARY KEY (seq_name))
     *
     * notice: $table is setted throw SYS_DB_SEQUENCE 
     * 
     * @access public
     * @param   string $fieldName  sequence name
     * @param   int    $step       sequence add step
     * @param   int    $start      sequence start number
     * @return  int                new sequence id
     */
    public function getSeq($fieldName, $step=1, $start=1){
     $table = SYS_DB_SEQUENCE;
        $step = (int)$step;
        $start = (int)$start;
     $this->execute("UPDATE $table SET seq_num=seq_num+($step) WHERE seq_name='$fieldName'");
        if($this->getAffectedRows()<1){
            $this->execute("INSERT INTO $table VALUES('$fieldName', $start)");
            $seq = $start;
        }else{
            $seq = $this->getOne("SELECT seq_num FROM $table WHERE seq_name='$fieldName'");
        }
        return $seq;
    }
    /**
     * Start a transaction
     * @access public
     */
    public function startTrans(){
     $this->mysqli->autocommit(false);
    }
    /**
     * rollback a transaction
     * @access public
     */
    public function failTrans(){
     $this->mysqli->rollback();
        $this->mysqli->autocommit(true);
    }
    /**
     * Complete a transaction
     * @access public
     */
    public function completeTrans(){
     $this->mysqli->commit();
        $this->mysqli->autocommit(false);
    }
    /**
     * get now transaction statistic
     * @access public
     * @return boolean
     */
    public function inTrans(){
        return $this->getOne("SELECT autocommit()");
    }
/**
 * destruct function
 * @access public
 */
public function __destruct(){
if($this-> mysqli) $this->mysqli->close();
}}
?>