execute(' ALTER TABLE msz_login_attempts CHANGE COLUMN attempt_user_agent attempt_user_agent TEXT NOT NULL COLLATE "utf8mb4_bin" AFTER attempt_created, ADD COLUMN attempt_client_info TEXT NULL DEFAULT NULL AFTER attempt_user_agent '); $conn->execute(' ALTER TABLE msz_sessions CHANGE column session_user_agent session_user_agent TEXT NOT NULL COLLATE "utf8mb4_bin" AFTER session_ip_last, ADD COLUMN session_client_info TEXT NULL DEFAULT NULL AFTER session_user_agent '); // make sure all existing fields have client info fields filled $updateLoginAttempts = $conn->prepare('UPDATE msz_login_attempts SET attempt_client_info = ? WHERE attempt_user_agent = ?'); $selectLoginAttempts = $conn->query('SELECT DISTINCT attempt_user_agent FROM msz_login_attempts'); while($selectLoginAttempts->next()) { $updateLoginAttempts->reset(); $userAgent = $selectLoginAttempts->getString(0); $updateLoginAttempts->addParameter(1, json_encode(ClientInfo::parse($userAgent))); $updateLoginAttempts->addParameter(2, $userAgent); $updateLoginAttempts->execute(); } $updateSessions = $conn->prepare('UPDATE msz_sessions SET session_client_info = ? WHERE session_user_agent = ?'); $selectSessions = $conn->query('SELECT DISTINCT session_user_agent FROM msz_sessions'); while($selectSessions->next()) { $updateSessions->reset(); $userAgent = $selectSessions->getString(0); $updateSessions->addParameter(1, json_encode(ClientInfo::parse($userAgent))); $updateSessions->addParameter(2, $userAgent); $updateSessions->execute(); } // make client info fields NOT NULL $conn->execute(' ALTER TABLE msz_login_attempts CHANGE COLUMN attempt_client_info attempt_client_info TEXT NOT NULL COLLATE "utf8mb4_bin" AFTER attempt_user_agent '); $conn->execute(' ALTER TABLE msz_sessions CHANGE COLUMN session_client_info session_client_info TEXT NOT NULL COLLATE "utf8mb4_bin" AFTER session_user_agent '); } }