У меня есть база данных MySQL, в которой есть некоторые хэши Murmur2 (в виде 64-битных целых чисел без знака), которые были сгенерированы с помощью Percona UDF, который поставляется с цепочкой Percona базы данных MySQL, найденной здесь https://github.com/percona/build-test/blob/master/plugin/percona-udf/murmur_udf.cc
Моя проблема в том, что теперь мне нужно сгенерировать те же хэши на стороне PHP, но я не могу найти или настроить что-либо существующее для работы / вывода одного и того же вывода для того же ввода.
Вещи, которые я пробовал:
Ошибка сегментации вызвана тем, что я запустил эту функцию
var_dump(murmurhash('Hello World'));
Что нормально работает, когда я загрузил https://github.com/kibae/php_murmurhash (исходное 32-битное расширение для создания хешей) и выполнил инструкции, но как только я заменил функцию (только отредактируйте файл MurmurHash2.cpp на https://github.com/StirlingMarketingGroup/php_murmurhash/blob/master/MurmurHash2.cpp), тот же вызов функции приведет к сбою скрипта PHP.
Вот функция PHP, которую я написал как порт из функции Percona C++.
function murmurhash2(string $s) : int {
$len = strlen($s);
$seed = 0;
$m = 0x5bd1e995;
$r = 24;
$h1 = $seed ^ $len;
$h2 = 0;
$i = 0;
while ($len >= 8) {
$k1 = ord($s[$i++]);
$k1 *= $m; $k1 ^= $k1 >> $r; $k1 *= $m;
$h1 *= $m; $h1 ^= $k1;
$len -= 4;
$k2 = ord($s[$i++]);
$k2 *= $m; $k2 ^= $k2 >> $r; $k2 *= $m;
$h2 *= $m; $h2 ^= $k2;
$len -= 4;
}
if ($len >= 4) {
$k1 = ord($s[$i++]);
$k1 *= $m; $k1 ^= $k1 >> $r; $k1 *= $m;
$h1 *= $m; $h1 ^= $k1;
$len -= 4;
}
switch ($len) {
case 3: $h2 ^= ord($s[2]) << 16;
case 2: $h2 ^= ord($s[1]) << 8;
case 1: $h2 ^= ord($s[0]);
$h2 *= $m;
};
$h1 ^= $h2 >> 18; $h1 *= $m;
$h2 ^= $h1 >> 22; $h2 *= $m;
$h1 ^= $h2 >> 17; $h1 *= $m;
$h = $h1;
$h = ($h << 32) | $h2;
return $h;
}
В MySQL я получаю это
select murmur_hash('Hello World'), cast(murmur_hash('Hello World')as unsigned), CONV(cast(murmur_hash('Hello World')as unsigned), 10, 16);
-- -8846466548632298438 9600277525077253178 853B098B6B655C3A
И в PHP я получаю
var_dump(murmurhash2('Hello World'));
// int(5969224437940092928)
Итак, глядя на результаты MySQL и PHP, ни подписанные, ни неподписанные результаты не соответствуют моему выводу PHP.
Есть ли что-то, что можно исправить с помощью любого из моих предыдущих двух подходов, или, может быть, уже работающий подход, который я могу использовать вместо этого?
@ user4581301 Я добавил немного больше о том, что я сделал для этого подхода, со ссылками на исходный файл и мой обновленный файл C++.
@ user4581301 Я создал собственное решение, которое сработало!






Я сам решил эту проблему, по сути перенеся хеш-функцию Percona непосредственно в PHP-расширение MySQL.
Инструкции по установке и использованию размещены здесь https://github.com/StirlingMarketingGroup/php-murmur-hash
В MySQL расширение Percona используется как
select`murmur_hash`('Yeet')
-- -7850704420789372250
А в PHP
php -r 'echo murmur_hash("Yeet");'
// -7850704420789372250
Обратите внимание, что они обрабатываются как целые числа со знаком для обеих сред, что вы можете решить в MySQL с помощью cast(`murmur_hash`('Yeet')as unsigned), но PHP не поддерживает целые числа без знака.
Порекомендуйте добавить в вопрос, как вы вызываете библиотеку C++ и что вы ей предоставляете. Некоторые умники здесь могут обнаружить, что пошло не так, и избавить от необходимости переносить алгоритм.