<?php

/**
 * THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 *
 * @package fusionLib
 * @copyright Copyright (c) 2012 fusionLib. All rights reserved.
 * @link http://fusionlib.com
 */

/**
 * flDbSQLite3Result Class
 *
 * Driver class to hold SQLite results.
 *
 * @package fusionLib
 */
class flDbSQLite3Result extends flDbResult {

	/**
	 * The result object.
	 *
	 * @var array
	 */
	private $results;

	/**
	 * The current index into the results.
	 *
	 * @var int
	 */
	private $idx = 0;

	/**
	 * Init the results object.
	 *
	 * @param PDOStatement $result The raw result data.
	 */
	function __construct($result) {
		$this->results = $result->fetchAll(PDO::FETCH_ASSOC);
	}

	/**
	 * Get the number of rows.
	 *
	 * @return int|void The number of rows in the results.
	 */
	function numRows() {
		return count($this->results);
	}

	/**
	 * Seek to a location in the results.
	 *
	 * @param int $row The row to seek to.
	 * @return bool true if the seek worked; else false.
	 */
	function seek($row) {
		$this->idx = $row;
		return $this->idx < count($this->results);
	}

	/**
	 * Fetch the next row from the results.
	 *
	 * @return array The row.
	 */
	function fetch() {
		return $this->idx < count($this->results) ? $this->results[$this->idx++] : false;
	}
}

/**
 * flDbSQLite3 Class
 *
 * Driver for SQLite database.
 *
 * @package fusionLib
 */
class flDbSQLite3 extends flDb {
	/**
	 * The master database link
	 *
	 * @var PDO
	 */
	private $masterDB = null;

	/**
	 * The number of rows affected.
	 *
	 * @var int
	 */
	private $affectedRows;

	/**
	 * Initialise the SQLite driver.
	 *
	 * @param array $master Array of the DSN parts for the master.
	 * @param string $slave The slave database DSN or null if not used.
	 * @throws flDbException
	 */
	function __construct($master, $slave) {
		try {
			$this->masterDB = new PDO('sqlite:' . FLROOTPATH . substr($master['path'], 1));
		} catch(PDOException $e) {
			throw new flDbException("Error connecting to database.\n\nError: " . $e->getMessage() . "\n" .
						"Error Number: " . $e->getCode());
		}
	}

	/**
	 * Escape a value in the driver.
	 *
	 * @param mixed $value The value to escape.
	 * @return mixed The escaped value.
	 */
	function _escape($value) {
		return trim($this->masterDB->quote($value), "'");
	}

	/**
	 * Perform the SQL query in the driver.
	 *
	 * @param string $query The query string.
	 * @return flDbResult The result object or boolean result.
	 */
	function _query($query) {
		$r = $this->masterDB->query($query);
		if(preg_match('/^SELECT|EXPLAIN/i', $query) && $r !== false) {
			$this->affectedRows = $r->rowCount();
			return new flDbSQLite3Result($r);
		}
		else
			return $r === false ? false : true;
	}

	/**
	 * Return the id generated by the last insert operation.
	 *
	 * @return int The id.
	 */
	function insertID() {
		return $this->masterDB->lastInsertId();
	}

	/**
	 * Get the number of rows affected by the previous operation.
	 *
	 * @return int The number of rows affected.
	 */
	function affectedRows() {
		return $this->affectedRows;
	}

	/**
	 * Get the list of tables in the database.
	 *
	 * @return array The list of tables in the database.
	 */
	function fetchTables() {
		$tables = array();
		$this->queryCount++;
		$result = $this->masterDB->query("SELECT name from sqlite_master WHERE type='table'");
		while($row = $result->fetch(PDO::FETCH_NUM))
			$tables[] = $row[0];
		return $tables;
	}

	/**
	 * Get the names of all fields in a table.
	 *
	 * @param string $table The table to query.
	 * @return array An array holding the names of all fields.
	 */
	function fetchFields($table) {
		$fields = array();
		$this->queryCount++;
		$result = $this->masterDB->query("PRAGMA TABLE_INFO($table)");
		while($row = $result->fetch(PDO::FETCH_NUM))
			$fields[] = $row[1];
		return $fields;
	}

	/**
	 * Optimize or repair tables within the database.
	 *
	 * @param bool $repair true to perform a repair or false to optimize.
	 * @param string $table The name of the table to operate on.
	 * @return string The result.
	 */
	function _maintain($repair, $table) {
		return 'OK';
	}

	/**
	 * The error for the previous operation.
	 *
	 * @return string The error string.
	 */
	function errorString() {
		$e = $this->masterDB->errorInfo();
		return "SQLSTATE[$e[0]] [$e[1]] $e[2]";
	}

	/**
	 * The database server version.
	 *
	 * @return string The version string.
	 */
	function version() {
		return $this->masterDB->getAttribute(PDO::ATTR_SERVER_VERSION);
	}
}
