1
0
mirror of git://f0xx.org/android_cast synced 2026-07-29 06:58:51 +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(); $pdo = Database::pdo();
$tables = Database::listTables($pdo); $tables = Database::listTables($pdo);
$out['tables'] = $tables; $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']) { if (!$out['tickets_table']) {
$out['tickets_migration'] = Database::ticketsMigrationHint(); $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 { public static function tableExists(PDO $pdo, string $table): bool {
if (self::isMysql()) { if (self::isMysql()) {
$db = cfg('db.mysql.database', 'androidcast_crashes'); // App DB users often lack information_schema visibility; SHOW TABLES uses normal grants.
$stmt = $pdo->prepare( $stmt = $pdo->query('SHOW TABLES LIKE ' . $pdo->quote($table));
'SELECT 1 FROM information_schema.tables if ($stmt !== false && $stmt->fetchColumn() !== false) {
WHERE table_schema = ? AND table_name = ? LIMIT 1' return true;
); }
$stmt->execute([$db, $table]); try {
return $stmt->fetchColumn() !== false; $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( $stmt = $pdo->prepare(
"SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = ? LIMIT 1" "SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = ? LIMIT 1"
@@ -539,13 +552,11 @@ final class Database {
/** @return list<string> */ /** @return list<string> */
public static function columnNames(PDO $pdo, string $table): array { public static function columnNames(PDO $pdo, string $table): array {
if (self::isMysql()) { if (self::isMysql()) {
$db = cfg('db.mysql.database', 'androidcast_crashes'); $stmt = $pdo->query('SHOW COLUMNS FROM ' . self::mysqlQuoteIdentifier($table));
$stmt = $pdo->prepare( if ($stmt === false) {
'SELECT column_name AS name FROM information_schema.columns return [];
WHERE table_schema = ? AND table_name = ?' }
); return array_column($stmt->fetchAll(PDO::FETCH_ASSOC), 'Field');
$stmt->execute([$db, $table]);
return array_column($stmt->fetchAll(PDO::FETCH_ASSOC), 'name');
} }
return array_column( return array_column(
$pdo->query('PRAGMA table_info(' . preg_replace('/[^a-z0-9_]/i', '', $table) . ')')->fetchAll(PDO::FETCH_ASSOC), $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> */ /** @return list<string> */
public static function listTables(PDO $pdo): array { public static function listTables(PDO $pdo): array {
if (self::isMysql()) { if (self::isMysql()) {
$db = cfg('db.mysql.database', 'androidcast_crashes'); $stmt = $pdo->query('SHOW TABLES');
$stmt = $pdo->prepare( if ($stmt === false) {
'SELECT table_name FROM information_schema.tables return [];
WHERE table_schema = ? ORDER BY table_name' }
); return array_values(array_filter($stmt->fetchAll(PDO::FETCH_COLUMN), 'is_string'));
$stmt->execute([$db]);
return $stmt->fetchAll(PDO::FETCH_COLUMN);
} }
return $pdo->query( return $pdo->query(
"SELECT name FROM sqlite_master WHERE type = 'table' ORDER BY name" "SELECT name FROM sqlite_master WHERE type = 'table' ORDER BY name"