<commit_before><?php

namespace FTB\core\db;
use SQLQuery;

class SchemaController {

	const ENGINE_MYSQL = 'mysql';
	const ENGINE_POSTGRES = 'postgresql';

	protected $db;
	protected $engine;

	public function __construct($db = '', $engine = self::ENGINE_MYSQL) {
		$this->db = $db;
		$this->engine = $engine;
	}

	public static function forge($db) {
		$engine = substr($db, 0, 3) === 'pg_' ? self::ENGINE_POSTGRES : self::ENGINE_MYSQL;
		switch ($engine) {
			case self::ENGINE_MYSQL:
				return new static($db, $engine);
			case self::ENGINE_POSTGRES:
				return new PostgresqlSchemaController($db);
		}
	}

	/******************************************************************/
	/************************** COLUMNS! ******************************/
	/******************************************************************/

	public function addColumn($table, $name, $type, $options = []) {
		return static::modifyColumn($table, $name, $type, $options, 'ADD');
	}

	public function modifyColumn($table, $name, $type, $options = [], $action = 'MODIFY') {
		if ($type !== 'TEXT' && strpos($type, 'VARCHAR') !== 0) {
			$options['charset'] = '';
			$options['collate'] = '';
		}
		switch ($this->engine) {
			case static::ENGINE_MYSQL:
			case static::ENGINE_POSTGRES:
				$query = SQLQuery::with($table, $this->db);
				$table = $query->quoteKeyword($table);
				$name = $query->quoteKeyword($name);
				$action = $action === 'ADD' ? 'ADD' : 'MODIFY';
				$sql = "ALTER TABLE $table $action COLUMN $name $type";
				if ($options['charset'] && $options['collate'] && $this->engine === static::ENGINE_MYSQL) {
					$sql .= " CHARACTER SET {$options['charset']} COLLATE {$options['collate']}";
				}
				if ($options['not_null']) {
					$sql .= " NOT NULL";
				}
				if (array_key_exists('default', $options)) {
					if ($options['default'] === null) {
						$sql .= " DEFAULT NULL";
					} else {
						$sql .= " DEFAULT " . $query->quote($options['default']);
					}
				}

				return $query->executeRawQuery($sql);

		}
	}

	public function dropColumn($table, $name) {
		$query = SQLQuery::with($table, $this->db);
		$table = $query->quoteKeyword($table);
		$name = $query->quoteKeyword($name);
		$sql = "ALTER TABLE $table DROP COLUMN $name";
		return $query->executeRawQuery($sql);
	}

	public function showColumns($table) {
		$query = SQLQuery::with($table, $this->db);
		$table = $query->quote($table);
		$query->executeRawQuery("SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = $table");
		$rows = [];
		while ($mysql_sucks = $query->fetchArray()) {
			$row = [];
			foreach ($mysql_sucks as $key => $value) {
				$row[strtolower($key)] = $value;
			}
			$rows[$row['column_name']] = $row;
		}
		return $rows;
	}

	/******************************************************************/
	/************************** INDEXES! ******************************/
	/******************************************************************/

	public function showIndexes($table) {
		$schema = $this->db ? : 'ourfa5_drupal';
		$rows = SQLQuery::with('information_schema.statistics', $this->db)
			->select(['index_name', 'index_type', 'column_name', 'non_unique'])
			->where([
				'table_schema' => $schema,
				'table_name' => $table,
				'index_type' => 'BTREE'
			])
			->order(['index_name' => 'ASC', 'seq_in_index' => 'ASC'])
			->as_arrays();

		$indexes = [];
		foreach ($rows as $row) {
			if (!$indexes[$row['index_name']]) {
				$indexes[$row['index_name']] = [
					'name' => $row['index_name'],
					'type' => strtolower($row['index_type']),
					'columns' => [$row['column_name']],
					'unique' => !$row['non_unique'],
				];
			} else {
				$indexes[$row['index_name']]['columns'][] = $row['column_name'];
			}
		}

		return $indexes;
	}

	public function addIndexes($table, array $indexes) {
		if (empty($indexes)) {
			throw new Exception('No indexes provided');
		}
		$query = SQLQuery::with($table, $this->db);
		$table = $query->quoteKeyword($table);<commit_msg>API: logging for the dashboard.  Fixed a few old QA and rating things to use SchemaController and App queries<commit_after><?php

namespace FTB\core\db;
use SQLQuery;

class SchemaController {

	const ENGINE_MYSQL = 'mysql';
	const ENGINE_POSTGRES = 'postgresql';

	protected $db;
	protected $engine;

	public function __construct($db = '', $engine = self::ENGINE_MYSQL) {
		$this->db = $db;
		$this->engine = $engine;
	}

	public static function forge($db) {
		$engine = substr($db, 0, 3) === 'pg_' ? self::ENGINE_POSTGRES : self::ENGINE_MYSQL;
		switch ($engine) {
			case self::ENGINE_MYSQL:
				return new static($db, $engine);
			case self::ENGINE_POSTGRES:
				return new PostgresqlSchemaController($db);
		}
	}

	/******************************************************************/
	/************************** COLUMNS! ******************************/
	/******************************************************************/

	public function addColumn($table, $name, $type, $options = []) {
		return static::modifyColumn($table, $name, $type, $options, 'ADD');
	}

	public function modifyColumn($table, $name, $type, $options = [], $action = 'MODIFY') {
		if ($type !== 'TEXT' && strpos($type, 'VARCHAR') !== 0) {
			$options['charset'] = '';
			$options['collate'] = '';
		}
		switch ($this->engine) {
			case static::ENGINE_MYSQL:
			case static::ENGINE_POSTGRES:
				$query = SQLQuery::with($table, $this->db);
				$table = $query->quoteKeyword($table);
				$name = $query->quoteKeyword($name);
				$action = $action === 'ADD' ? 'ADD' : 'MODIFY';
				$sql = "ALTER TABLE $table $action COLUMN $name $type";
				if ($options['charset'] && $options['collate'] && $this->engine === static::ENGINE_MYSQL) {
					$sql .= " CHARACTER SET {$options['charset']} COLLATE {$options['collate']}";
				}
				if ($options['not_null']) {
					$sql .= " NOT NULL";
				}
				if (array_key_exists('default', $options)) {
					if ($options['default'] === null) {
						$sql .= " DEFAULT NULL";
					} else {
						$sql .= " DEFAULT " . $query->quote($options['default']);
					}
				}

				return $query->executeRawQuery($sql);

		}
	}

	public function dropColumn($table, $name) {
		$query = SQLQuery::with($table, $this->db);
		$table = $query->quoteKeyword($table);
		$name = $query->quoteKeyword($name);
		$sql = "ALTER TABLE $table DROP COLUMN $name";
		return $query->executeRawQuery($sql);
	}

	public function showColumns($table, Array $column_names = []) {
		$query = SQLQuery::with($table, $this->db);
		$table = $query->quote($table);
		$query_str = "SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = $table";

		if ($column_names) {
			$query_str .= " AND column_name in (";
			foreach ($column_names as $column_name) {
				$query_str .= $query->quote($column_name) . ',';
			}
			$query_str = rtrim($query_str, ',');
			$query_str .= ")";
		}
		$query->executeRawQuery($query_str);
		$rows = [];
		while ($mysql_sucks = $query->fetchArray()) {
			$row = [];
			foreach ($mysql_sucks as $key => $value) {
				$row[strtolower($key)] = $value;
			}
			$rows[$row['column_name']] = $row;
		}
		return $rows;
	}

	public function hasColumn($table, $column) {
		return count(self::showColumns($table, [$column])) === 1;
	}

	/******************************************************************/
	/************************** INDEXES! ******************************/
	/******************************************************************/

	public function showIndexes($table) {
		$schema = $this->db ? : 'ourfa5_drupal';
		$rows = SQLQuery::with('information_schema.statistics', $this->db)
			->select(['index_name', 'index_type', 'column_name', 'non_unique'])
			->where([
				'table_schema' => $schema,
				'table_name' => $table,
				'index_type' => 'BTREE'
			])
			->order(['index_name' => 'ASC', 'seq_in_index' => 'ASC'])
			->as_arrays();

		$indexes = [];
		foreach ($rows as $row) {
			if (!$indexes[$row['index_name']]) {
				$indexes[$row['index_name']] = [
					'name' => $row['index_name'],
					'type' => strtolower($row['index_type']),
					'columns' => [$row['column_name']],
					'unique' => !$row['non_unique'],
				];
			} else {
				$indexes[$row['index_name']]['columns'][] = $row['column_name'];
			}
		}

		return $indexes;
	}

	public function addIndexes($table, array $indexes) {
		if (empty($indexes)) {
			throw new \Exception('No indexes provided');
		}
		$query = SQLQuery::with($table, $this->db);
		$table = $query->quoteKeyword($table);
{'fraction_non_alphanumeric': 0.2773109243697479, 'fraction_numerical': 0.0010652148183216948, 'mean_word_length': 4.365079365079365, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 74, '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': '7419822', 'n_tokens_mistral': 3222, 'n_tokens_neox': 2778, 'n_words': 544}