Creating UDF for Impala (C++, Docker, Crypto lib)
В связи с тем, что в Impala отсутствуют многие функции доступные на обычных РСУБД, например, Upper/Lower для кириллицы, или хэш-функции md5, sha256 для сверки контрольных сумм и пр. вещей, то появляется необходимость создавать свои User Defint Function. Легче и быстрее всего UDF создать на проде, но, к сожалению, данный вариант не всегда доступен в связи с тем, что при компиляции той или иной UDF могут возникнуть проблемы с версионностью и взаимозависимостью библиотек etc. Одно из решений данной проблемы это воспользоваться docker образом, что и сделаем далее ниже.
И так, для этого нам потребуется установка:
- Если у вас ОС Windows, то понадобиться установить программу виртуализации, например, VirtualBox, чтобы развернуть ОС на базе Linux, на Win на мой взгляд, Docker работает неполноценно.
- Устанавливаем Docker
- Скачиваем Docker образ под ОС, которая у вас на проде
docker pull oraclelinux7.5
- Переходим в папку с Dockerfile-OS ("-OS" уберите перед запуском), и собираем образ с ОС и инструментами для разработки UDF
cd /path
docker build -t impala-udf-base .
- Создаем новый образ на основе предыдущего образа, где компилируем hash UDF
4.1 Перходим в папку с UDF (udfimp)
cd /path
4.2 Клонируем в него репозиторий криптографии
git clone https://github.com/weidai11/cryptopp
4.3 Клонируем в него репозиторий с базовым сэмплом от Cloudera
4.4 В папке с Dockerfile-UDF запускаем новую сборку ("-UDF" уберите перед запуском). В результате у вас скомпилируется нужная динамическая библиотека.
docker build -t image name .
- Создаем и запускаем Docker-контейнер из Docker-образа
docker run -it -d --name имя контейнера impala-udf-base
- Копируем необходимые файлы или папку из контейнера на хост-машину, в нашем случае папка /udfmp/build - там будет сгенерированная динамическая библиотека libudfcrypto.so
docker cp id контейнера:/path_docker_container "/path_local"
cd "/path_local"
Далее способ 2
- Копирование с хост-машины в контейнер, в нашем случае надо туда перенести папку impala-udf-master
docker cp "/path_local" id контейнера:/path_docker_container
- Входим в docker-контейнер
docker exec -t -i dd7518a91b66 /bin/bash
- Далее заходим в нужную папку (impala-udf-master) и компилим cmake . && make в результате получим несколько .so библиотек для создания пользовательских функций Upper, Lower, String, Date etc.
- Переносим полученные .so на прод сервер в папку /user/impala/udfs
Создаем пользовательские функции по аналогии:
create function if not exists sha256(string) returns string location '/user/impala/udfs/libudfcrypto.so' SYMBOL='SHA256';
create function if not exists md5(string) returns string location '/user/impala/udfs/libudfcrypto.so' SYMBOL='MD5';
create function if not exists upper_ruutf8(string) returns string location '/user/impala/udfs/libudf-strings.so' SYMBOL='upper_ruutf8';
create function if not exists lower_ruutf8(string) returns string location '/user/impala/udfs/libudf-strings.so' SYMBOL='lower_ruutf8';
create function if not exists length_ruutf8_str(string) returns string location '/user/impala/udfs/libudf-strings.so' SYMBOL='length_ruutf8_str';
create function if not exists substr_ruutf8_str(string,string,string) returns string location '/user/impala/udfs/libudf-strings.so' SYMBOL='substr_ruutf8_str';
create function if not exists substr2_ruutf8_str(string,string) returns string location '/user/impala/udfs/libudf-strings.so' SYMBOL='substr2_ruutf8_str';
create function if not exists translate_ruutf8(string,string,string) returns string location '/user/impala/udfs/libudf-strings.so' SYMBOL='translate_ruutf8';
Примеры select'а:
Нижний/верхний регистр для кириллицы
select default.lower_ruutf8("привет валЕт"), default.upper_ruutf8("привет валЕт")
Длина строки для кириллицы
select
default.length_ruutf8_str("привет валЕт")
Позволяет извлекать подстроку из строки
select default.substr_ruutf8_str("привет валЕт",'1','10'), default.substr2_ruutf8_str("привет валЕт",'5')
Замена символов по маске
select
default.translate_ruutf8('KFC PRIMORSKAYA CAFE','qwerенгшщASDFРОЛД','mnbячсмPIIYTЙЦУК')
Хэш-сумма
select
default.md5("hive"),
default.sha256("hive")