asdasd
This commit is contained in:
@@ -246,7 +246,13 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(payload.error || 'API request failed');
|
const context = payload && payload.context && typeof payload.context === 'object' ? payload.context : null;
|
||||||
|
const detail = context
|
||||||
|
? [context.message, context.statement ? `SQL: ${String(context.statement).slice(0, 500)}` : null]
|
||||||
|
.filter(Boolean)
|
||||||
|
.join(' ')
|
||||||
|
: '';
|
||||||
|
throw new Error([payload.error || 'API request failed', detail].filter(Boolean).join(' '));
|
||||||
}
|
}
|
||||||
if (payload && Object.prototype.hasOwnProperty.call(payload, 'data')) {
|
if (payload && Object.prototype.hasOwnProperty.call(payload, 'data')) {
|
||||||
return payload.data;
|
return payload.data;
|
||||||
@@ -1471,7 +1477,11 @@
|
|||||||
? `Geloeschte Tabellen: ${result.dropped_tables.join(', ')}.`
|
? `Geloeschte Tabellen: ${result.dropped_tables.join(', ')}.`
|
||||||
: 'Keine Tabellen geloescht.')
|
: 'Keine Tabellen geloescht.')
|
||||||
);
|
);
|
||||||
await loadBootstrap(projectKey);
|
try {
|
||||||
|
await loadBootstrap(projectKey);
|
||||||
|
} catch (bootstrapError) {
|
||||||
|
setError(`Schema wurde initialisiert, aber Bootstrap-Daten konnten nicht geladen werden: ${bootstrapError.message}`);
|
||||||
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setError(err.message);
|
setError(err.message);
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
@@ -379,53 +379,7 @@ final class Router
|
|||||||
|
|
||||||
private function simpleSchemaStatus(): array
|
private function simpleSchemaStatus(): array
|
||||||
{
|
{
|
||||||
$requiredTables = [
|
return $this->schemaManager()->schemaStatus();
|
||||||
$this->config->tablePrefix() . 'projects',
|
|
||||||
$this->config->tablePrefix() . 'currencies',
|
|
||||||
$this->config->tablePrefix() . 'settings',
|
|
||||||
$this->config->tablePrefix() . 'cost_plans',
|
|
||||||
$this->config->tablePrefix() . 'measurements',
|
|
||||||
$this->config->tablePrefix() . 'fx_fetches',
|
|
||||||
$this->config->tablePrefix() . 'measurement_rates',
|
|
||||||
$this->config->tablePrefix() . 'payouts',
|
|
||||||
$this->config->tablePrefix() . 'targets',
|
|
||||||
$this->config->tablePrefix() . 'dashboard_definitions',
|
|
||||||
$this->config->tablePrefix() . 'miner_offers',
|
|
||||||
$this->config->tablePrefix() . 'purchased_miners',
|
|
||||||
];
|
|
||||||
|
|
||||||
$presentTables = $this->fetchTablesByPrefix($this->config->tablePrefix());
|
|
||||||
$presentRequired = array_values(array_intersect($requiredTables, $presentTables));
|
|
||||||
$missingTables = array_values(array_diff($requiredTables, $presentRequired));
|
|
||||||
$pendingUpgrades = [];
|
|
||||||
|
|
||||||
if (in_array($this->config->tablePrefix() . 'cost_plans', $presentRequired, true)) {
|
|
||||||
$columns = $this->fetchColumns($this->config->tablePrefix() . 'cost_plans');
|
|
||||||
foreach (['mining_speed_value', 'mining_speed_unit', 'bonus_speed_value', 'bonus_speed_unit'] as $column) {
|
|
||||||
if (!in_array($column, $columns, true)) {
|
|
||||||
$pendingUpgrades[] = 'cost_plan_speed_columns';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
!in_array($this->config->tablePrefix() . 'fx_fetches', $presentTables, true) ||
|
|
||||||
!in_array($this->config->tablePrefix() . 'fx_rates', $presentTables, true)
|
|
||||||
) {
|
|
||||||
$pendingUpgrades[] = 'fx_rates_table';
|
|
||||||
}
|
|
||||||
|
|
||||||
return [
|
|
||||||
'required_tables' => $requiredTables,
|
|
||||||
'present_tables' => $presentRequired,
|
|
||||||
'missing_tables' => $missingTables,
|
|
||||||
'present_count' => count($presentRequired),
|
|
||||||
'missing_count' => count($missingTables),
|
|
||||||
'pending_upgrades' => array_values(array_unique($pendingUpgrades)),
|
|
||||||
'pending_upgrade_count' => count(array_unique($pendingUpgrades)),
|
|
||||||
'all_present' => $missingTables === [],
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function rebuildPreservingCoreData(string $projectKey): array
|
private function rebuildPreservingCoreData(string $projectKey): array
|
||||||
@@ -606,38 +560,6 @@ final class Router
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function fetchTablesByPrefix(string $prefix): array
|
|
||||||
{
|
|
||||||
$pdo = $this->pdo();
|
|
||||||
$driver = (string) $pdo->getAttribute(PDO::ATTR_DRIVER_NAME);
|
|
||||||
|
|
||||||
if ($driver === 'pgsql') {
|
|
||||||
$sql = 'SELECT table_name FROM information_schema.tables WHERE table_schema = current_schema() AND table_name LIKE :prefix ORDER BY table_name';
|
|
||||||
} else {
|
|
||||||
$sql = 'SELECT table_name FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name LIKE :prefix ORDER BY table_name';
|
|
||||||
}
|
|
||||||
|
|
||||||
$statement = $pdo->prepare($sql);
|
|
||||||
$statement->execute(['prefix' => $prefix . '%']);
|
|
||||||
return array_map('strval', $statement->fetchAll(PDO::FETCH_COLUMN) ?: []);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function fetchColumns(string $tableName): array
|
|
||||||
{
|
|
||||||
$pdo = $this->pdo();
|
|
||||||
$driver = (string) $pdo->getAttribute(PDO::ATTR_DRIVER_NAME);
|
|
||||||
|
|
||||||
if ($driver === 'pgsql') {
|
|
||||||
$sql = 'SELECT column_name FROM information_schema.columns WHERE table_schema = current_schema() AND table_name = :table_name ORDER BY ordinal_position';
|
|
||||||
} else {
|
|
||||||
$sql = 'SELECT column_name FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = :table_name ORDER BY ordinal_position';
|
|
||||||
}
|
|
||||||
|
|
||||||
$statement = $pdo->prepare($sql);
|
|
||||||
$statement->execute(['table_name' => $tableName]);
|
|
||||||
return array_map('strval', $statement->fetchAll(PDO::FETCH_COLUMN) ?: []);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function refreshFxRates(array $input): array
|
private function refreshFxRates(array $input): array
|
||||||
{
|
{
|
||||||
$base = strtoupper(trim((string) ($input['base'] ?? 'EUR')));
|
$base = strtoupper(trim((string) ($input['base'] ?? 'EUR')));
|
||||||
|
|||||||
@@ -379,20 +379,39 @@ final class SchemaManager
|
|||||||
|
|
||||||
$sql = (string) file_get_contents($schemaFile);
|
$sql = (string) file_get_contents($schemaFile);
|
||||||
$statements = preg_split('/;\s*(?:\R|$)/', $sql) ?: [];
|
$statements = preg_split('/;\s*(?:\R|$)/', $sql) ?: [];
|
||||||
|
$currentStatement = null;
|
||||||
|
$useTransaction = $this->driver === 'pgsql' && !$this->pdo->inTransaction();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
if ($useTransaction) {
|
||||||
|
$this->pdo->beginTransaction();
|
||||||
|
}
|
||||||
|
|
||||||
foreach ($statements as $statement) {
|
foreach ($statements as $statement) {
|
||||||
$trimmed = trim($statement);
|
$trimmed = trim($statement);
|
||||||
if ($trimmed === '') {
|
if ($trimmed === '') {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
$currentStatement = $trimmed;
|
||||||
$this->pdo->exec($trimmed);
|
$this->pdo->exec($trimmed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($useTransaction && $this->pdo->inTransaction()) {
|
||||||
|
$this->pdo->commit();
|
||||||
|
}
|
||||||
} catch (\Throwable $exception) {
|
} catch (\Throwable $exception) {
|
||||||
|
if ($useTransaction && $this->pdo->inTransaction()) {
|
||||||
|
$this->pdo->rollBack();
|
||||||
|
}
|
||||||
|
|
||||||
throw new ApiException(
|
throw new ApiException(
|
||||||
'Schema-Import fuer Mining-Checker fehlgeschlagen.',
|
'Schema-Import fuer Mining-Checker fehlgeschlagen.',
|
||||||
500,
|
500,
|
||||||
['message' => $exception->getMessage()]
|
[
|
||||||
|
'message' => $exception->getMessage(),
|
||||||
|
'schema_file' => $schemaFile,
|
||||||
|
'statement' => $currentStatement !== null ? substr($currentStatement, 0, 1000) : null,
|
||||||
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user