View File Name : Normalization.php
';
return $htmlOutput;
}
/**
* find all the possible partial dependencies based on data in the table.
*
* @param string $table current table
* @param string $db current database
*
* @return string HTML containing the list of all the possible partial dependencies
*/
public function findPartialDependencies($table, $db)
{
$dependencyList = [];
$this->dbi->selectDb($db);
$columns = (array) $this->dbi->getColumnNames(
$db,
$table
);
$columns = (array) Util::backquote($columns);
$totalRowsRes = $this->dbi->fetchResult(
'SELECT COUNT(*) FROM (SELECT * FROM '
. Util::backquote($table) . ' LIMIT 500) as dt;'
);
$totalRows = $totalRowsRes[0];
$primary = Index::getPrimary($table, $db);
$primarycols = $primary === false ? [] : $primary->getColumns();
$pk = [];
foreach ($primarycols as $col) {
$pk[] = Util::backquote($col->getName());
}
$partialKeys = $this->getAllCombinationPartialKeys($pk);
$distinctValCount = $this->findDistinctValuesCount(
array_unique(
array_merge($columns, $partialKeys)
),
$table
);
foreach ($columns as $column) {
if (in_array($column, $pk)) {
continue;
}
foreach ($partialKeys as $partialKey) {
if (! $partialKey
|| ! $this->checkPartialDependency(
$partialKey,
$column,
$table,
$distinctValCount[$partialKey],
$distinctValCount[$column],
$totalRows
)
) {
continue;
}
$dependencyList[$partialKey][] = $column;
}
}
$html = __(
'This list is based on a subset of the table\'s data '
. 'and is not necessarily accurate. '
)
. '
';
foreach ($dependencyList as $dependon => $colList) {
$html .= '
'
. ''
. ''
. htmlspecialchars(str_replace('`', '', (string) $dependon)) . ' -> '
. ''
. htmlspecialchars(str_replace('`', '', implode(', ', $colList)))
. ''
. '';
}
if (empty($dependencyList)) {
$html .= '
'
. __('No partial dependencies found!') . '
';
}
$html .= '
';
return $html;
}
/**
* check whether a particular column is dependent on given subset of primary key
*
* @param string $partialKey the partial key, subset of primary key,
* each column in key supposed to be backquoted
* @param string $column backquoted column on whose dependency being checked
* @param string $table current table
* @param int $pkCnt distinct value count for given partial key
* @param int $colCnt distinct value count for given column
* @param int $totalRows total distinct rows count of the table
*
* @return bool TRUE if $column is dependent on $partialKey, False otherwise
*/
private function checkPartialDependency(
$partialKey,
$column,
$table,
$pkCnt,
$colCnt,
$totalRows
) {
$query = 'SELECT '
. 'COUNT(DISTINCT ' . $partialKey . ',' . $column . ') as pkColCnt '
. 'FROM (SELECT * FROM ' . Util::backquote($table)
. ' LIMIT 500) as dt;';
$res = $this->dbi->fetchResult($query, null, null);
$pkColCnt = $res[0];
if ($pkCnt && $pkCnt == $colCnt && $colCnt == $pkColCnt) {
return true;
}
return $totalRows && $totalRows == $pkCnt;
}
/**
* function to get distinct values count of all the column in the array $columns
*
* @param array $columns array of backquoted columns whose distinct values
* need to be counted.
* @param string $table table to which these columns belong
*
* @return array associative array containing the count
*/
private function findDistinctValuesCount(array $columns, $table)
{
$result = [];
$query = 'SELECT ';
foreach ($columns as $column) {
if (! $column) {
continue;
}
//each column is already backquoted
$query .= 'COUNT(DISTINCT ' . $column . ') as \''
. $column . '_cnt\', ';
}
$query = trim($query, ', ');
$query .= ' FROM (SELECT * FROM ' . Util::backquote($table)
. ' LIMIT 500) as dt;';
$res = $this->dbi->fetchResult($query, null, null);
foreach ($columns as $column) {
if (! $column) {
continue;
}
$result[$column] = $res[0][$column . '_cnt'] ?? null;
}
return $result;
}
/**
* find all the possible partial keys
*
* @param array $primaryKey array containing all the column present in primary key
*
* @return array containing all the possible partial keys(subset of primary key)
*/
private function getAllCombinationPartialKeys(array $primaryKey)
{
$results = [''];
foreach ($primaryKey as $element) {
foreach ($results as $combination) {
$results[] = trim($element . ',' . $combination, ',');
}
}
array_pop($results); //remove key which consist of all primary key columns
return $results;
}
}