<?php
/**
 * PostgresDatabaseAdaptor
 * PostgreSQL接続
 * データベースコネクション情報
 * $Id: PostgresDatabaseAdaptor.inc,v 1.1 2015/10/08 11:18:57 wanggb Exp $
 * @author iimuro
 * @access public
 * @package jp.aimslib2.database.postgres
 */

class PostgresDatabaseAdaptor{

	public $host;
	public $port;
	public $db_name;
	public $user;
	public $pass;

	public $con = null;
	public $result;
	public $lastquery;

	/**
	 * コンストラクタ
	 */
	function PostgresDatabaseAdaptor(){
	}

	/**
	 * 初期化
	 */
	public function init($host, $port, $db_name, $user, $pass){
		$this->host = $host;
		if(isset($port)){
			$this->port = $port;
		}else{
			$this->port = "5432";
		}
		$this->db_name = $db_name;
		$this->user = $user;
		$this->pass = $pass;
	}

	/**
	 * 接続の確立
	 */
	public function db_connect(){
		if (!is_resource($this->con)) {
			$h = "host=" . $this->host . " port=" . $this->port . " dbname=" . $this->db_name . " user=" . $this->user . " password=" . $this->pass;
			$this->con = pg_connect($h);
		}
	}


	/**
	 * 接続の解除（使わない）
	 */
	public function db_close() {
		pg_close($this->con);
		$this->con = null;
	}


	public function db_exec($query) {
		$this->db_connect();
		$this->lastquery = $query;

		// test
		ErrorLogger::doOutput("SQL:" . $query);

		//$this->result = pg_query($this->con, $query);
		if(@$this->result = pg_query($this->con, $query)){

			$rowset = $this->private_getRowset($this->result);
			pg_free_result($this->result);
			return $rowset;
		} else {
			if ( pg_connection_status($this->con) == PGSQL_CONNECTION_OK ){
				ErrorLogger::doOutput("connect ok", 0);
			}
			error_log(pg_result_error(), 0);
			error_log(pg_last_error(), 0);
			error_log("error at:" . $this->lastquery, 0);
			pg_query("ROLLBACK");

			return "QUERY_ERROR";
			//exit;
		}
	}

	/**
	 * データの一括挿入
	 */
	public function db_copy_from($table, $data, $delimiter = "\t"){
		$this->db_connect();


		pg_exec($this->con, "copy " . $table . " from stdin");
		foreach($data as $line){
			pg_put_line($this->con, $line);
		}
		return pg_end_copy($this->con);

		//return pg_copy_from($this->con, $table, $data, $delimiter);
	}


	/**
	 * ラージオブジェクトを保存します。OIDが指定されない場合は新規に作成します。
	 * この処理を行う前にはかならずトランザク ションブロックの中に括る必要があります。
	 * @access public
	 * @param string $data ラージオブジェクトバイナリデータ
	 * @param int $oid ラージオブジェクトOID
	 * @return int ラージオブジェクトOID。失敗時はnull。
	 */
	public static function writeLargeObject($data, $oid = null) {
		$this->db_connect();
		if ($oid == null) {
			if (!$oid = pg_lo_create($this->con)) {
				return null;
			}
		}
		if (!$handle = pg_lo_open($this->con, $oid, "w")) {
			return null;
		}
		if (!pg_lo_write($handle, $data)) {
			pg_lo_close($handle);
			return null;
		}
		if (!pg_lo_close($handle)) {
			return null;
		}

		return $oid;
	}


	/**
	 * ラージオブジェクトを読み出します。
	 * この処理を行う前にはかならずトランザク ションブロックの中に括る必要があります。
	 * @access public
	 * @param int $oid ラージオブジェクトOID
	 * @return int ラージオブジェクトバイナリデータ。失敗時はnull。
	 */
	public static function readLargeObject($oid) {
		$this->db_connect();
		if (!$handle = pg_lo_open($this->con, $oid, "r")) {
			return null;
		}
		ob_start();
		if (!pg_lo_read_all($handle)) {
			pg_lo_close($handle);
			return null;
		}
		$data = ob_get_contents();
		ob_end_clean();
		if (!pg_lo_close($handle)) {
			return null;
		}

		return $data;
	}

	/**
	 * ラージオブジェクトを削除します。
	 * この処理を行う前にはかならずトランザク ションブロックの中に括る必要があります。
	 * @access public
	 * @param int $oid ラージオブジェクトOID
	 * @return boolean 成功時true
	 */
	public static function deleteLargeObject($oid) {
		ErrorLogger::doOutput("UnsupportedFunctionException.", 0);
		$this->db_connect();
		if ($oid != null) {
			if (pg_lo_unlink($this->con, $oid)) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 結果を２次元連想配列にして返します。
	 * @access private
	 * @param resource $result 検索の結果リソース
	 * @return array カラム名をkeyとした連想配列を要素として持つ配列
	 */
	public function private_getRowset(&$result){
		$rowset = array();
		if (!is_resource($result)) {
			return null;
		}
		$bool_field = array();
		for ($x = 0; $x < pg_num_fields($result); $x++ ) {
			if (pg_field_type($result, $x) == "bool") {
				$name = pg_field_name($result, $x);
				array_push($bool_field, $name);
			}
		}
		while ($row = pg_fetch_assoc($result)) {
			foreach ($bool_field as $name) {
				if ($row[$name] == "t") {
					$row[$name] = true;
				} else {
					$row[$name] = false;
				}
			}
			array_push($rowset, $row);
		}

		return $rowset;
	}
}

?>