В этом разделе приведена процедура добавления новой ``родной'' функции. Следует учитывать, что в бинарную поставку ``родные'' функции добавить невозможно, поскольку эта процедура требует изменения исходного кода MySQL. Поэтому необходимо собственноручно компилировать MySQL из поставки исходного текста. Кроме того, при переходе на другую версию MySQL (например, при выпуске новой версии) все изменения придется повторить для этой новой версии.
Чтобы добавить новую ``родную'' функцию MySQL, необходимо выполнить следующие действия:
Добавьте в
lex.h
одну строку, определяющую имя новой функции в массивеsql_functions[]
.Если прототип функции простой (вообще без аргументов или принимает один, два или три аргумента), то в
lex.h
вторым аргументом в массивеsql_functions[]
следует указатьSYM(FUNC_ARG#)
(где # количество аргументов) и добавить вitem_create.cc
функцию, создающую объект функции. В качестве примеров можно рассмотретьABS
иcreate_funcs_abs()
. Если прототип функции сложный (например, принимает переменное число аргументов), то следует добавить две строки вsql_yacc.yy
. Одна строка служит для указания препроцессору, какой символ должен определитьyacc
(строку следует добавить в начало файла). Затем определяются параметры функции и правило разбораsimple_expr
пополняется "элементом" с этими параметрами. Чтобы получить представление о том, как это делается, в качестве примера просмотрите все вхожденияATAN
вsql_yacc.yy
.В
item_func.h
объявляется класс, наследуемый отItem_num_func
илиItem_str_func
, в зависимости от того, какое значение возвращает функция - числовое или строковое.-
В
item_func.cc
добавьте одно из следующих объявлений, в зависимости от того, какая функция определяется - числовая или строковая:double Item_func_newname::val() longlong Item_func_newname::val_int() String *Item_func_newname::Str(String *str)
Если объект наследуется от любого стандартного элемента (подобного
Item_num_func
), то, возможно, потребуется определить только одну из перечисленных выше функций и возложить на родительский объект заботу об остальных функциях. Например, классItem_str_func
определяет функциюval()
, выполняющуюatof()
над значением, возвращенным::str()
. -
Возможно, понадобится также определить следующую функцию объекта:
void Item_func_newname::fix_length_and_dec()
Эта функция должна как минимум вычислять
max_length
на основе переданных аргументов.max_length
является максимальным количеством символов, которое может возвращать функция. Эта функция также должна устанавливатьmaybe_null = 0
, если невозможно, чтобы главная функция возвратила значениеNULL
. Узнать, может ли какой-либо аргумент функции возвращатьNULL
, функция может путем проверки поля/переменнойmaybe_null
аргумента. В качестве типичного примера того, как это делается, можно рассмотретьItem_func_mod::fix_length_and_dec
.
Все функции должны поддерживать многопоточность (другими словами, непозволительно использовать какие-либо глобальные или статические переменные в функции без их защиты примитивами взаимного исключения).
Если желательно возвращать NULL
, из ::val()
, ::val_int()
или ::str()
, то
необходимо устанавливать null_value
в 1
и возвращать 0
.
Для функции объекта ::str()
существуют следующие дополнительные аспекты:
Аргумент
String *str
обеспечивает строковый буфер, который может быть использован для размещения результата (дополнительную информацию о типеString
можно найти в файлеsql_string.h
).Функция
::str()
должна возвращать строку, содержащую результат, или(char*) 0
, если результатNULL
.На сегодняшний день при написании всех строковых функций принято избегать какого бы то ни было распределения памяти, за исключением случаев, когда это абсолютно необходимо!