<?php
/**
 * DatabaseDriver for firebird
 *
 * Database class presents abstract handling for any type of RDBMS or data collection(php array, xml, csv ....)
 *
 * LICENSE: This source file is subject to GNU GENERAL PUBLIC LICENSE Version 3
 * http://www.gnu.org/licenses/gpl-3.0.txt.
 *
 * @package    LabbitBox
 * @subpackage DB
 * @copyright  2010 LabbitBox Development Team.
 * @license    GPL v3 http://www.gnu.org/licenses/gpl-3.0.txt
 * @author     minotaur <minotaur@labbitbox.org>
 * @version    v0.1
 * @since      -
 * @link       http://labbitbox.org/
 * @see        http://labbitbox.org/
 */
require_once(dirname(__FILE__).'/../common.php');
require_once(dirname(__FILE__).'/DB_Driver.php');
class DB_Driver_firebird extends DB_Driver{

    protected $_db;

	public function __construct($parent){
		parent::__construct($parent);
        ini_set('ibase.timestampformat', '%Y/%m/%d %H:%M:%S');
        ini_set('ibase.dateformat',      '%Y/%m/%d');
        ini_set('ibase.timeformat',      '%H:%M:%S');
	}

	public function __destruct(){
		// not implemented yet
	}

	public function connect($server, $port, $databasePath, $userName, $password, $characterSet=NULL){
        if($port==3050){
            if($server=='localhost'){
                $mixedServer = NULL;
            }else{
                $mixedServer = "$server:";
            }
        }else{
            $mixedServer = "$server/$port:";
        }
		return ibase_pconnect("$mixedServer$databasePath", $userName, $password);
	}

	public function disconnect($connection){
		return ibase_close($connection);
	}


	/**
     * start transaction for firebird
	 *
	 * not follow 2-phase-commit yet.
	 * if you are interested in this, see following URL.
	 * http://www.php.net/manual/ja/function.ibase-trans.php
     *
     * @param NativeConnection $connection
     *
	 * @return NativeTransaction transsaction
	 */
	public function startTransaction($connection){
		//return ibase_trans(IBASE_COMMITTED||IBASE_REC_NO,$connection);
		return ibase_trans();
	}



	/**
     * commit transaction for firebird
     *
     * @param NativeConnection $connection
     *
	 * @return bool TRUE or FALSE
	 */
	public function commit($transaction=NULL, $terminate=FALSE){
        if($terminate){
            return ibase_commit($transaction);
        }else{
            return ibase_commit_ret($transaction);
        }
	}



	/**
     * rollback transaction for firebird
     *
     * @param NativeConnection $connection
     *
	 * @return bool TRUE or FALSE
	 */
	public function rollback($transaction=NULL){
		return ibase_rollback($transaction);
	}



	/**
     * checkpoint transaction for firebird
     *
     * @param NativeConnection $connection
     *
	 * @return bool TRUE or FALSE
	 */
	public function checkpoint($transaction=NULL){
		return $this->commit($transaction);
	}

	/**
	 * query
	 *
	 * クエリが失敗した場合、FALSE を返します。成功した場合、 (SELECT クエリのような) 結果の行がある場合、結果 ID を返します。 クエリが成功し、結果がない場合は TRUE を返します。
	 * 注意:
	 * PHP 5.0.0 以降では、INSERT・UPDATE・DELETE 文に対してはこの関数は 変更された行数を返します。後方互換性を確保するため、これらの文で クエリが成功したものの 1 行も更新されなかった場合には TRUE を返します。
	 */
	public function query($sql, $transaction=NULL){
        if($transaction){
            return ibase_query($transaction, $sql);
        }else{
            return ibase_query($sql);
        }
	}



    /**
     * get error code
     *
     * @return integer ErrorCode
     */
    public function errCode(){
        return ibase_errcode();
    }



    /**
     * get error message
     *
     * @return string ErrorMessage
     */
    public function errMessage(){
        return ibase_errmsg();
    }



    /**
     * check error
     *
     * @return boolean TRUE:ERROR, FALSE:NOT ERROR
     */
    public function errCheck(){
        if(ibase_errcode()){
            return TRUE;
        }else{
            return FALSE;
        }
    }



    /**
     * fetch
     *
     * @param object $nativeDataset
     *
     * @return mixed mixed array as a record image.
     **/
	public function fetch($nativeDataset){
		return ibase_fetch_assoc($nativeDataset, IBASE_TEXT);
	}



    /**
     * free result
     *
     * @param mxed $nativeDataset
     *
     * @return boolean Always TRUE
     */
    public function freeResult($nativeDataset){
        return ibase_free_result($nativeDataset);
    }



    public function tables(){
        $ds     = $this->_db->dataset('SHOW_TABLES');
        $tables = $ds->getAll();
        return trim_r($tables);
    }

    public function fields($tableName){
        $ds = $this->_db->dataset('SHOW_TABLE', array(':TABLE_NAME'=>$tableName));
        $fields    = $ds->getAll();
        //print_r($fields);
        $srcFields = trim_r($fields);
        //$srcFields = $fields;
        //print_r($srcFields);

        $iField = 0;
        foreach($srcFields as $curValue){
            $destFields[$iField]['POSITION'     ]    = $curValue['FPOSITION'];
            $destFields[$iField]['NAME'         ]    = $curValue['FNAME'];
            $destFields[$iField]['DESCRIPTION'  ]    = $curValue['FDESCRIPTION'];
            //$destFields[$iField]['TYPE'         ]    = $curValue['FTYPE'];
            $destFields[$iField]['BYTE_LENGTH'  ]    = $curValue['FBYTE_LEN'];
            $destFields[$iField]['CHAR_LENGTH'  ]    = $curValue['FCHAR_LEN'];
            $destFields[$iField]['PRECISION'    ]    = $curValue['FPRECISION'];
            $destFields[$iField]['SCALE'        ]    = $curValue['FSCALE'];
            $destFields[$iField]['SUBTYPE'      ]    = $curValue['FSUBTYPE'];
            $destFields[$iField]['NULL'         ]    = $curValue['FNULL'];
            $destFields[$iField]['DEFAULT'      ]    = $curValue['FDEFAULT'];
            $destFields[$iField]['CHARACTER_SET']    = $curValue['FCSET'];
            $destFields[$iField]['COLLATION'    ]    = $curValue['FCOLLATION'];
            switch($curValue['FTYPE']){
                case 'SHORT':
                    $destFields[$iField]['SQL_DATATYPE'] = 'SMALLINT';
                    $destFields[$iField]['STD_DATATYPE'] = 'integer';
                    break;
                case 'LONG':
                    $destFields[$iField]['SQL_DATATYPE'] = 'INTEGER';
                    $destFields[$iField]['STD_DATATYPE'] = 'integer';
                    break;
                case 'INT64':
                    $destFields[$iField]['SQL_DATATYPE'] = 'BIGINT';
                    $destFields[$iField]['STD_DATATYPE'] = 'integer';
                    break;
                case 'DOUBLE':
                    $destFields[$iField]['SQL_DATATYPE'] = 'DOUBLE PRECISION';
                    $destFields[$iField]['STD_DATATYPE'] = 'double';
                    break;
                case 'DATE':
                    $destFields[$iField]['SQL_DATATYPE'] = 'DATE';
                    $destFields[$iField]['STD_DATATYPE'] = 'date';
                    break;
                case 'TIME':
                    $destFields[$iField]['SQL_DATATYPE'] = 'TIME';
                    $destFields[$iField]['STD_DATATYPE'] = 'time';
                    break;
                case 'TIMESTAMP':
                    $destFields[$iField]['SQL_DATATYPE'] = 'TIMESTAMP';
                    $destFields[$iField]['STD_DATATYPE'] = 'timestamp';
                    break;
                case 'VARYING':
                    $destFields[$iField]['SQL_DATATYPE'] = 'VARCHAR';
                    $destFields[$iField]['STD_DATATYPE'] = 'string';
                    break;
                case 'TEXT':
                    $destFields[$iField]['SQL_DATATYPE'] = 'CHAR';
                    $destFields[$iField]['STD_DATATYPE'] = 'string';
                    break;
                default:
                    $destFields[$iField]['SQL_DATATYPE'] = 'UNKNOWN('.$curValue['FTYPE'].')';
                    $destFields[$iField]['STD_DATATYPE'] = 'unknown('.$curValue['FTYPE'].')';
            }
            $iField++;
        }
        return $destFields;
    }

    public function primaryKeys($tableName){
        $primaryKeys = $this->_db->dataset('GET_PRIMARY_KEYS', array(':TABLE_NAME'=>$tableName))->getAll();
        return trim_r($primaryKeys);
    }

    /**
     * getRecordInfo
     *
     * @param object $nativeDataset
     *
     * @return mixed mixed array as a field information.
     **/
	public function getRecordInfo($nativeDataset){
		$fieldCount = ibase_num_fields($nativeDataset);
		for($iField=0; $iField<$fieldCount; $iField++){
			$srcInfo = ibase_field_info($nativeDataset, $iField);
			$info[$srcInfo['name']]['name']     = $srcInfo['name']    ;
			$info[$srcInfo['name']]['alias']    = $srcInfo['alias']   ;
			$info[$srcInfo['name']]['relation'] = $srcInfo['relation'];
			$info[$srcInfo['name']]['length']   = $srcInfo['length']  ;
			$info[$srcInfo['name']]['type']     = $srcInfo['type']    ;
		}
		return $info;
	}





}
?>
