query($sql); } self::ensureColumn( 'system_session_activity', 'customer_number_context', 'ALTER TABLE system_session_activity ADD COLUMN customer_number_context INT NULL AFTER principal_id' ); self::ensureColumn( 'system_session_activity', 'device_type', "ALTER TABLE system_session_activity ADD COLUMN device_type VARCHAR(16) NOT NULL DEFAULT 'unknown' AFTER customer_number_context" ); self::ensureColumn( 'system_session_activity', 'user_agent', 'ALTER TABLE system_session_activity ADD COLUMN user_agent VARCHAR(1024) NULL AFTER device_type' ); self::ensureColumn( 'system_session_activity', 'last_route', 'ALTER TABLE system_session_activity ADD COLUMN last_route VARCHAR(255) NULL AFTER user_agent' ); self::ensureColumn( 'system_session_activity', 'first_seen_at', 'ALTER TABLE system_session_activity ADD COLUMN first_seen_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP AFTER last_route' ); self::ensureColumn( 'system_session_activity', 'last_seen_at', 'ALTER TABLE system_session_activity ADD COLUMN last_seen_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP AFTER first_seen_at' ); self::ensureColumn( 'system_session_activity', 'created_at', 'ALTER TABLE system_session_activity ADD COLUMN created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP AFTER last_seen_at' ); self::ensureColumn( 'system_session_activity', 'updated_at', 'ALTER TABLE system_session_activity ADD COLUMN updated_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP AFTER created_at' ); self::$initialized = true; } public static function tableHasColumn(string $table, string $column): bool { global $db; $table = $db->escape_string($table); $column = $db->escape_string($column); $database = $db->escape_string($db->getDatabase()); $sql = "SELECT COUNT(*) AS c FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = '$database' AND TABLE_NAME = '$table' AND COLUMN_NAME = '$column'"; $result = $db->query($sql); if (!$result) { return false; } $row = $result->fetch_assoc(); return ((int)($row['c'] ?? 0)) > 0; } public static function ensureColumn(string $table, string $column, string $alterSql): void { global $db; if (self::tableHasColumn($table, $column)) { return; } $db->query($alterSql); } }