<commit_before><?php

declare(strict_types=1);

namespace bed;

require_once 'Col.php';

/**
 * Database abstraction.
 */
class Database {

	protected $dbh;
	protected $config;
	protected $pdoOptions;
	protected $lastStmt;

	/**
	 * Accepts a readable array with the properties needed to build the
	 * connection string. Plus, an array with PDO options for fine-grain
	 * configuration.
	 */
	public function __construct(array $config, array $pdoOptions = null) {
		// Check presence of required attributes
		foreach (['type', 'host', 'name', 'user', 'pass'] as $attr)
			if (!$config[$attr])
				throw new \InvalidArgumentException(
					"The '$attr' is required to configure the database");

		$this->config = $config;
		$this->pdoOptions = $pdoOptions;
	}

	/**
	 * Obtain the instance representing the database connection (AKA database
	 * handler). This allows for accessing transaction control and other
	 * functionality.
	 */
	public function get(): \PDO {
		// Establish the connection only if the database instance is requested,
		// and only the first time
		if (!$this->dbh) {
			$connStr = $this->config['type']
					. ':host=' . $this->config['host']
					. ';dbname=' . $this->config['name']
					. ';charset=' . ($this->config['charset'] ?? 'utf8mb4');

			$this->dbh = new \PDO(
				$connStr,
				$this->config['user'],
				$this->config['pass'],
				$this->pdoOptions
			);
		}
		return $this->dbh;
	}

	/**
	 * Return the last run statement.
	 */
	public function getLastStatement() {
		return $this->lastStmt;
	}

	/**
	 * Simple wrapper for running database queries.
	 *
	 * @param $q Database query to be run, as a string. Alternatively, an
	 * already-prepared statement can be provided, so that the preparation
	 * can be done simply once.
	 * @param $params List of parameter values. Optionally, an associative
	 * element can be provided, whose key would indicate the type (given as
	 * one of Col's functions), and whose value would be the actual value of
	 * the parameter, overriding the auto-detection.
	 * @param $colTypes List of types in the form of a Col function, which may
	 * be needed for SELECT statements.
	 *
	 * NOTE this function relies on the PDOStatement::getColumnMeta function
	 * (http://php.net/manual/en/pdostatement.getcolumnmeta.php) to simplify
	 * the queries, but this function is marked as EXPERIMENTAL. Thus, please
	 * verify it is working in your particular conditions before using.
	 */
	public function run($q, array $params = [], array $colTypes = []) {
		$isSelect = $this->isSelect($q);
		if (!$isSelect && $colTypes)
			throw new \InvalidArgumentException(
				'There is no point on providing column types in non-SELECT statements');

		if (is_string($q))
			$stmt = $this->lastStmt = $this->get()->prepare($q);<commit_msg>Simplify comment<commit_after><?php

declare(strict_types=1);

namespace bed;

require_once 'Col.php';

/**
 * Database abstraction.
 */
class Database {

	protected $dbh;
	protected $config;
	protected $pdoOptions;
	protected $lastStmt;

	/**
	 * Accepts a readable array with the properties needed to build the
	 * connection string. Plus, an array with PDO options for fine-grain
	 * configuration.
	 */
	public function __construct(array $config, array $pdoOptions = null) {
		// Check presence of required attributes
		foreach (['type', 'host', 'name', 'user', 'pass'] as $attr)
			if (!$config[$attr])
				throw new \InvalidArgumentException(
					"The '$attr' is required to configure the database");

		$this->config = $config;
		$this->pdoOptions = $pdoOptions;
	}

	/**
	 * Obtain the instance representing the database connection (AKA database
	 * handler). This allows for accessing transaction control and other
	 * functionality.
	 */
	public function get(): \PDO {
		// Establish the connection only if the database instance is requested,
		// and only the first time
		if (!$this->dbh) {
			$connStr = $this->config['type']
					. ':host=' . $this->config['host']
					. ';dbname=' . $this->config['name']
					. ';charset=' . ($this->config['charset'] ?? 'utf8mb4');

			$this->dbh = new \PDO(
				$connStr,
				$this->config['user'],
				$this->config['pass'],
				$this->pdoOptions
			);
		}
		return $this->dbh;
	}

	/**
	 * Return the last run statement.
	 */
	public function getLastStatement() {
		return $this->lastStmt;
	}

	/**
	 * Simple wrapper for running database queries.
	 *
	 * @param $q Database query to be run, as a string. Alternatively, an
	 * already-prepared statement can be provided, so that the preparation
	 * can be done simply once.
	 * @param $params List of parameter values. Optionally, an associative
	 * element can be provided, whose key would indicate the type (given as
	 * one of Col's functions), and whose value would be the actual value of
	 * the parameter, overriding the auto-detection.
	 * @param $colTypes List of types in the form of a Col function, which may
	 * be needed for SELECT statements.
	 *
	 * NOTE run() relies on PDOStatement::getColumnMeta()
	 * (http://php.net/manual/en/pdostatement.getcolumnmeta.php) to simplify
	 * the queries, which is marked as EXPERIMENTAL; thus, please verify it
	 * is working in your particular conditions before using.
	 */
	public function run($q, array $params = [], array $colTypes = []) {
		$isSelect = $this->isSelect($q);
		if (!$isSelect && $colTypes)
			throw new \InvalidArgumentException(
				'There is no point on providing column types in non-SELECT statements');

		if (is_string($q))
			$stmt = $this->lastStmt = $this->get()->prepare($q);
{'fraction_non_alphanumeric': 0.12869502523431867, 'fraction_numerical': 0.0010814708002883922, 'mean_word_length': 3.593543046357616, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3169451', 'n_tokens_mistral': 1809, 'n_tokens_neox': 1588, 'n_words': 591}