<?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) 2008 - 2013 fusionLib. All rights reserved.
 * @link http://fusionlib.com
 */

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

	/**
	 * The result object.
	 *
	 * @var resource
	 */
	private $result;

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

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

	/**
	 * 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) {
		return @sqlite_seek($this->result, $row);
	}

	/**
	 * Fetch the next row from the results.
	 *
	 * @return array The row.
	 */
	function fetch() {
		return sqlite_fetch_array($this->result, SQLITE_ASSOC);
	}
}

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

	/**
	 * 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) {
		$error = '';
		if(!$this->masterDB = sqlite_open(FLROOTPATH . substr($master['path'], 1), 0666, $error)) {
			throw new flDbException("Error connecting to database.\n\nError: $error\n");
		}
	}

	/**
	 * Close the database.
	 */
	function __destruct() {
		@sqlite_close($this->masterDB);
	}

	/**
	 * Escape a value in the driver.
	 *
	 * @param mixed $value The value to escape.
	 * @return mixed The escaped value.
	 */
	function _escape($value) {
		return sqlite_escape_string($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 = @sqlite_query($this->masterDB, str_replace('`', "'", $query));
		if(preg_match('/SELECT|EXPLAIN/i', $query) && $r !== false)
			return new flDbSQLiteResult($r);
		else
			return $r === false ? false : true;
	}

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

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

	/**
	 * Get the list of tables in the database.
	 *
	 * @return array The list of tables in the database.
	 */
	function fetchTables() {
		$tables = array();
		$this->queryCount++;
		$result = sqlite_query($this->masterDB, "SELECT name from sqlite_master WHERE type='table'");
		while($row = sqlite_fetch_array($result, SQLITE_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 = sqlite_query($this->masterDB, "PRAGMA TABLE_INFO($table)");
		while($row = sqlite_fetch_array($result, SQLITE_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() {
		return sqlite_error_string(sqlite_last_error($this->masterDB));
	}

	/**
	 * The database server version.
	 *
	 * @return string The version string.
	 */
	function version() {
		return sqlite_libversion();
	}
}
