Новости
Документация
Download
Webboard
Поиск
FAQ/ЧаВо
Обратная связь




Справочное руководство по MySQL

9.2.2 Добавление новой определяемой пользователем функции

    9.2.2 Добавление новой определяемой пользователем функции

    Для того чтобы работал механизм UDF, функции должны быть написаны на C или на C++, а используемая операционная система должна поддерживать динамическую загрузку. В поставку исходного кода входит файл `sql/udf_example.cc', в котором определены пять новых функций. К этому файлу следует обращаться, если нужно узнать, как работает соглашение о вызовах UDF.

    Чтобы mysqld имел возможность использовать UDF-функции, необходимо сконфигурировать MySQL с --with-mysqld-ldflags=-rdynamic. Причина здесь в том, что на многих платформах (включая Linux) можно загружать динамическую библиотеку (посредством dlopen()) из статически скомпонованной программы, получаемой при использовании --with-mysqld-ldflags=-all-static. Если есть потребность использовать UDF, которой нужно обращаться к символам из mysqld (как в примере функции methaphone из `sql/udf_example.cc', которая использует default_charset_info), то программу необходимо компоновать с -rdynamic (обращайтесь к man dlopen).

    Для каждой функции, которую предполагается использовать в командах SQL, следует определять соответствующие функции C (или C++). В дальнейшем в качестве имени для примера функции мы будем использовать имя xxx. Чтобы различать применение в SQL и C/C++, для вызова SQL-функции мы будем использовать обозначение XXX() (прописными), а xxx() (строчными) - для вызова функции C/C++.

    Для реализации интерфейса для XXX() требуются следующие функции C/C++:

    xxx() (обязательная)
    Главная функция. Она вычисляет результат функции. Соответствие между типами SQL и возвращаемым типом функции C/C++ показано в приведенной ниже таблице:
    Тип SQL Тип C/C++
    STRING char *
    INTEGER long long
    REAL double
    xxx_init() (необязательная)
    Функция инициализации для xxx(). Может быть использована:
    • для проверки количества аргументов к XXX();
    • для проверки того, что аргументы имеют требуемый тип или, в противном случае, для указания MySQL приводить аргументы к нужным типам при вызове главной функции;
    • для распределения всей памяти, требуемой основной функцией;
    • для задания максимальной длины результата;
    • для задания (для REAL-функций) максимального числа десятичных знаков после запятой;
    • для указания, может ли результатом быть NULL.
    xxx_deinit() (необязательная)
    Функция деинициализации для xxx(). Должна освобождать всю память, выделенную функцией инициализации.

    При запуске SQL-команды XXX() MySQL вызывает функцию инициализации xxx_init(), чтобы дать ей возможность выполнить все необходимые установки, такие как проверка аргументов и распределение памяти. Если xxx_init() возвращает ошибку, то выполнение SQL-команды прерывается с сообщением об ошибке, а главная функция и функция деинициализации не вызываются. В противном случае для каждой строки вызывается главная функция xxx(). После того как будут обработаны все строки, вызывается функция деинициализации xxx_deinit(), чтобы выполнить необходимую очистку.

    Для агрегатных функций (подобных SUM()) необходимо также подготовить следующие функции:

    xxx_reset() (обязательная)
    Сбрасывает сумму и обрабатывает аргумент как начальное значение для новой группы.
    xxx_add() (обязательная)
    Добавляет аргумент к имеющейся сумме.

    При использовании агрегатных UDF-функций MySQL работает следующим образом:

    1. Вызывается xxx_init(), чтобы агрегатная функция могла распределить память, которая понадобится для хранения результатов.
    2. Таблица сортируется в соответствии с выражением GROUP BY.
    3. Для первой строки новой группы вызывается функция xxx_reset().
    4. Для каждой новой строки, принадлежащей к той же группе, вызывается функция xxx_add().
    5. Когда группа меняется, или после завершения обработки последней строки вызывается xxx() для получения итога.
    6. Повторяются шаги 3-5, пока не будут обработаны все строки.
    7. Вызывается xxx_deinit(), чтобы UDF могла освободить всю распределенную ею память.

    Все функции должны поддерживать многопоточность (не только главная, но также и функции инициализации и деинициализации). Это означает, что непозволительно распределять какие-либо глобальные или статические переменные с изменяющимися значениями! Если требуется память, то ее следует распределять в xxx_init() и освобождать в xxx_deinit().

    Главы


Поиск по документации:



РЕКЛАМА НА САЙТЕ
  Создание сайтов | |