Документация Firebird → Документация по Firebird → NULL в СУБД Firebird → Обработка NULL в UDF |
UDF (User Defined Functions - функции, определяемые пользователем) - это функции, которые не являются внутренними функциями ядра, они определены в отдельных (внешних) модулях. СУБД Firebird сопровождается двумя библиотеками UDF: ib_udf (унаследованная от СУБД InterBase) и fbudf. Вы можете добавить другие библиотеки, например купив их, скачав их из Интерента, или написав самостоятельно. UDF не могут использоваться «автоматически», как встроенные функции, - сначала их нужно «декларировать» в базе данных. Это так же верно и для UDF, которые поставляются в стандартных библиотеках с СУБД Firebird.
Рассказ о том, как объявлять, использовать и писать UDF выходит за пределы темы, рассматриваемой этим руководством. Однако, мы должны предупредить вас, что UDF порой выполняют неожиданное преобразование NULL. Иногда это приводит к тому, что входной NULL конвертируется в обыкновенное значение, а в других случаях происходит изменение верного входного значения, например, '' (пустая строка), на NULL.
Основной причиной этой проблемы является «старый стиль» вызова UDF, при котором невозможно передать NULL в качестве входного аргумента функции. Когда вызывается такая функция, как LTRIM (отсечение слева) с аргументом NULL, аргумент передается в функцию в виде пустой строки. Изнутри функции нет способа определить, является ли аргумент действительно пустой строкой или значением NULL. Что же в таком случае делать автору функции? У него есть выбор: либо брать аргумент по полученному значению, либо считать, что первоначально это был NULL и поступать с ним соответственно.
В зависимости от типа результата, вернуть NULL может быть возможным, даже если получить NULL невозможно. Таким образом, могут произойти следующие неожиданные вещи:
Вы вызваете функцию с аргументом NULL. Он передается как значение, например, 0 или ''. Внутри функции этот аргумент не изменяется назад на NULL, и возвращается не-NULL результат.
Вы вызываете функцию с верным аргументом, таким как 0 или ''. Он передается как есть (очевидно). Но код функции предполагает, что это значение на самом деле представляет собой NULL, и, ввиду отсутствия других ориентиров, трактует и возвращает его как NULL.
Оба преобразования являются не желательными, но второе, вероятно, более не желательно, чем первое (лучше предположить значение для NULL, чем утерять верное значение). Если вернуться к нашему примеру с LTRIM: до версии Firebird 1.0.3 (включительно) эта функция возвращала NULL, если вы передавали ей пустую строку; а начиная с версии 1.5 она больше не возвращает NULL. В этих последних версиях строка NULL «обрезается» до пустой строки. Это не правильно, но здесь выбрано меньшее из двух зол: в более ранней версии верные пустые строки безжалостно превращались в NULL - строки с неизвестным значением.
Нежелательные преобразования, описанные выше, обычно случаются только со старыми (давно существующими и не адаптировавшимися) библиотеками UDF, но их существует довольно много (чаще всего встречается в ib_udf). Также, ничего не предостерегает небрежного разработчика от подобных ошибок в функциях нового стиля. Итак, если вы используете UDF и не знаете, как функция ведет себя с аргументами, содержащими NULL, то:
Посмотрите на декларацию функции, чтобы увидеть, как передаются аргументы и возвращаются значения. Если там сказано «by descriptor», это должно быть безопасно (хотя осуществить дополнительную проверку никогда не помешает). Во всех остальных случаях обратитесь к остальным пунктам.
Если у вас есть исходный код и вы понимаете язык, на котором написана библиотека функций (например, C/C++), проверьте код функции.
Проверьте функцию на корректность ее работы с входным параметром NULL и с обычным входным параметром, который может быть интерпретирован функцией как NULL (0 для числовых аргументов и/или '' для строковых аргументов).
Если функция выполняет нежелательное преобразование NULL <-> не-NULL, вы должны учитывать это в вашем коде прежде, чем будете вызывать UDF (смотрите также Проверка на NULL где-то в этом руководстве).
Декларации функций для сопровождающих библиотек UDF могут быть найдены в подкаталоге Firebird bin/examples (v. 1.0) или bin/UDF (v. 1.5 и старше). Смотрите файлы с расширением .sql
Чтобы больше узнать об UDF, обратитесь к InterBase 6.0 Developer's Guide (скачать бесплатно на http://www.ibphoenix.com/downloads/60DevGuide.zip), Using Firebird и Firebird Reference Guide (оба на CD), или Firebird Book. CD и книга могут быть приобретены через http://www.ibphoenix.com/.
Документация Firebird → Документация по Firebird → NULL в СУБД Firebird → Обработка NULL в UDF |