Fix manticore indexes check

This commit is contained in:
DariusIII
2026-07-15 15:31:00 +02:00
parent 6210b86e8e
commit 091b4b1265
4 changed files with 127 additions and 10 deletions
+2 -2
View File
@@ -37,8 +37,8 @@ final class InspectManticore extends Command
}
$actual = $client->table($table)->describe();
$comparison = ManticoreSchemaInspector::compareColumns(is_array($actual) ? $actual : [], $definition['columns']);
$actualSettings = $client->sql("SHOW TABLE {$table} SETTINGS", true);
$missingSettings = ManticoreSchemaInspector::missingSettings($actualSettings, $definition['settings']);
$actualSettings = $client->tables()->settings(['table' => $table]);
$missingSettings = ManticoreSchemaInspector::missingSettings($actualSettings, ManticoreIndexRegistry::inspectableSettings());
$needsRebuild = $comparison['missing'] !== [] || $comparison['incompatible'] !== [] || $missingSettings !== [];
$report['tables'][$table] = [...$comparison, 'missing_settings' => $missingSettings, 'needs_rebuild' => $needsRebuild];
$report['compatible'] = $report['compatible'] && ! $needsRebuild;
@@ -83,6 +83,14 @@ final class ManticoreIndexRegistry
};
}
/** @return array<string, int|string> */
public static function inspectableSettings(): array
{
// Manticore 28 omits defaults/no-op settings such as min_prefix_len=0
// and exact_words from SHOW TABLE ... SETTINGS / SHOW CREATE TABLE.
return ['min_infix_len' => 2, 'index_field_lengths' => 1];
}
/** @param array<string, string> $configuredIndexes */
public static function logicalName(string $table, array $configuredIndexes = []): ?string
{
@@ -12,24 +12,24 @@ final class ManticoreSchemaInspector
*/
public static function missingSettings(mixed $actual, array $expected): array
{
$encoded = strtolower((string) json_encode($actual));
$settings = self::normalizeSettings($actual);
return array_values(array_filter(array_keys($expected), static function (string $setting) use ($encoded, $expected): bool {
return ! str_contains($encoded, strtolower($setting))
|| ! str_contains($encoded, strtolower((string) $expected[$setting]));
return array_values(array_filter(array_keys($expected), static function (string $setting) use ($settings, $expected): bool {
return ! array_key_exists(strtolower($setting), $settings)
|| $settings[strtolower($setting)] !== strtolower((string) $expected[$setting]);
}));
}
/**
* @param array<int, array<string, mixed>> $actual
* @param array<int|string, array<string, mixed>> $actual
* @param array<string, array<string, mixed>> $expected
* @return array{missing: list<string>, incompatible: array<string, array{expected: string, actual: string}>}
*/
public static function compareColumns(array $actual, array $expected): array
{
$types = [];
foreach ($actual as $column) {
$name = (string) ($column['Field'] ?? $column['field'] ?? '');
foreach ($actual as $key => $column) {
$name = (string) ($column['Field'] ?? $column['field'] ?? (is_string($key) ? $key : ''));
$type = strtolower((string) ($column['Type'] ?? $column['type'] ?? ''));
if ($name !== '') {
$types[$name] = $type;
@@ -42,11 +42,67 @@ final class ManticoreSchemaInspector
$expectedType = strtolower((string) $definition['type']);
if (! isset($types[$name])) {
$missing[] = $name;
} elseif (! str_contains($types[$name], $expectedType)) {
} elseif (! self::typesAreCompatible($types[$name], $expectedType)) {
$incompatible[$name] = ['expected' => $expectedType, 'actual' => $types[$name]];
}
}
return ['missing' => $missing, 'incompatible' => $incompatible];
}
private static function typesAreCompatible(string $actual, string $expected): bool
{
if ($expected === 'integer') {
return str_contains($actual, 'integer') || str_contains($actual, 'uint');
}
return str_contains($actual, $expected);
}
/** @return array<string, string> */
private static function normalizeSettings(mixed $actual): array
{
if (! is_array($actual)) {
return [];
}
$settings = [];
foreach ($actual as $key => $value) {
if (is_string($key) && ! is_array($value)) {
if (strtolower($key) === 'settings' && is_string($value)) {
foreach (preg_split('/\R/', $value) ?: [] as $line) {
if (preg_match('/^\s*([a-z0-9_]+)\s*=\s*[\'\"]?([^\'\"]+?)[\'\"]?\s*$/i', $line, $match) === 1) {
$settings[strtolower($match[1])] = strtolower(trim($match[2]));
}
}
continue;
}
$settings[strtolower($key)] = strtolower((string) $value);
continue;
}
if (! is_array($value)) {
continue;
}
$name = $value['Setting_name'] ?? $value['setting_name'] ?? $value['Variable_name'] ?? $value['variable_name'] ?? $value['Name'] ?? $value['name'] ?? null;
$settingValue = $value['Value'] ?? $value['value'] ?? null;
if (is_string($name) && $settingValue !== null) {
$settings[strtolower($name)] = strtolower((string) $settingValue);
continue;
}
if (is_string($key)) {
$nestedValue = $value['Value'] ?? $value['value'] ?? reset($value);
if (is_scalar($nestedValue)) {
$settings[strtolower($key)] = strtolower((string) $nestedValue);
}
}
}
return $settings;
}
}