diff --git a/examples/crash_reporter/backend/public/api/diag.php b/examples/crash_reporter/backend/public/api/diag.php index 336f01b..ae36bdc 100644 --- a/examples/crash_reporter/backend/public/api/diag.php +++ b/examples/crash_reporter/backend/public/api/diag.php @@ -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(); } diff --git a/examples/crash_reporter/backend/src/Database.php b/examples/crash_reporter/backend/src/Database.php index b187d13..aea8e3b 100644 --- a/examples/crash_reporter/backend/src/Database.php +++ b/examples/crash_reporter/backend/src/Database.php @@ -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 */ 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 */ 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"