1
0
mirror of git://f0xx.org/android_cast synced 2026-07-29 05:17:39 +03:00

Fix MariaDB tickets table detection for app DB users.

Use SHOW TABLES/COLUMNS instead of information_schema so requireTicketsTable() works when the table exists but the app user cannot read metadata catalogs.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Anton Afanasyeu
2026-05-24 22:52:26 +02:00
parent b5e83e4b4f
commit 483f635843
2 changed files with 38 additions and 22 deletions

View File

@@ -41,7 +41,14 @@ try {
$pdo = Database::pdo();
$tables = Database::listTables($pdo);
$out['tables'] = $tables;
$out['tickets_table'] = in_array('tickets', $tables, true);
$out['tickets_table'] = Database::ticketsTableExists($pdo);
if (Database::isMysql()) {
try {
$out['mysql_database'] = $pdo->query('SELECT DATABASE()')->fetchColumn();
} catch (Throwable $e) {
$out['mysql_database'] = $e->getMessage();
}
}
if (!$out['tickets_table']) {
$out['tickets_migration'] = Database::ticketsMigrationHint();
}

View File

@@ -519,15 +519,28 @@ final class Database {
);
}
private static function mysqlQuoteIdentifier(string $name): string {
return '`' . str_replace('`', '``', $name) . '`';
}
public static function tableExists(PDO $pdo, string $table): bool {
if (self::isMysql()) {
$db = cfg('db.mysql.database', 'androidcast_crashes');
$stmt = $pdo->prepare(
'SELECT 1 FROM information_schema.tables
WHERE table_schema = ? AND table_name = ? LIMIT 1'
);
$stmt->execute([$db, $table]);
return $stmt->fetchColumn() !== false;
// App DB users often lack information_schema visibility; SHOW TABLES uses normal grants.
$stmt = $pdo->query('SHOW TABLES LIKE ' . $pdo->quote($table));
if ($stmt !== false && $stmt->fetchColumn() !== false) {
return true;
}
try {
$pdo->query('SELECT 1 FROM ' . self::mysqlQuoteIdentifier($table) . ' LIMIT 0');
return true;
} catch (PDOException $e) {
$sqlState = $e->getCode();
$errno = (int) ($e->errorInfo[1] ?? 0);
if ($sqlState === '42S02' || $errno === 1146) {
return false;
}
throw $e;
}
}
$stmt = $pdo->prepare(
"SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = ? LIMIT 1"
@@ -539,13 +552,11 @@ final class Database {
/** @return list<string> */
public static function columnNames(PDO $pdo, string $table): array {
if (self::isMysql()) {
$db = cfg('db.mysql.database', 'androidcast_crashes');
$stmt = $pdo->prepare(
'SELECT column_name AS name FROM information_schema.columns
WHERE table_schema = ? AND table_name = ?'
);
$stmt->execute([$db, $table]);
return array_column($stmt->fetchAll(PDO::FETCH_ASSOC), 'name');
$stmt = $pdo->query('SHOW COLUMNS FROM ' . self::mysqlQuoteIdentifier($table));
if ($stmt === false) {
return [];
}
return array_column($stmt->fetchAll(PDO::FETCH_ASSOC), 'Field');
}
return array_column(
$pdo->query('PRAGMA table_info(' . preg_replace('/[^a-z0-9_]/i', '', $table) . ')')->fetchAll(PDO::FETCH_ASSOC),
@@ -556,13 +567,11 @@ final class Database {
/** @return list<string> */
public static function listTables(PDO $pdo): array {
if (self::isMysql()) {
$db = cfg('db.mysql.database', 'androidcast_crashes');
$stmt = $pdo->prepare(
'SELECT table_name FROM information_schema.tables
WHERE table_schema = ? ORDER BY table_name'
);
$stmt->execute([$db]);
return $stmt->fetchAll(PDO::FETCH_COLUMN);
$stmt = $pdo->query('SHOW TABLES');
if ($stmt === false) {
return [];
}
return array_values(array_filter($stmt->fetchAll(PDO::FETCH_COLUMN), 'is_string'));
}
return $pdo->query(
"SELECT name FROM sqlite_master WHERE type = 'table' ORDER BY name"