Есть два способа добавить новую функцию в MySQL:
- Вы можете добавить функцию через механизм определяемых пользователем
функций (user-definable function, UDF). Они добавляются динамически, используя
команды
CREATE FUNCTION
и DROP FUNCTION
.
- Вы можете добавить функцию как внутреннюю в MySQL. Такие функции
компилируются прямо внутрь сервера
mysqld
и становятся доступными
на постоянной основе.
Каждый метод имеет свои проблемы:
- Если Вы пишете определяемую пользователем функцию, Вы должны установить
объектный файл в дополнение к серверу. Если Вы компилируете Вашу функцию прямо
в сервер, Вы не должны делать этого.
- Вы можете добавлять UDF к двоичному дистрибутиву MySQL. Встроенные функции
требуют, чтобы Вы изменили исходники.
- Если Вы обновляете MySQL, Вы можете продолжать использовать Ваш
предварительно установленный UDF. Для встроенных функций Вы должны повторить
модификации каждый раз, когда Вы делаете апгрейд.
Независимо от метода, который Вы используете, чтобы добавить новые функции,
они могут использоваться точно так же как местные функции типа
ABS()
или SOUNDEX()
.
CREATE [AGGREGATE] FUNCTION function_name RETURNS {STRING|REAL|INTEGER}
SONAME shared_library_name
DROP FUNCTION function_name
Определяемые пользователем функции (user-definable function, UDF)
представляют собой способ расширить MySQL новой функцией, которая работает
подобно местным (встроенным) функциям MySQL типа ABS()
или
CONCAT()
.
AGGREGATE
новая опция для MySQL Version 3.23. Функция с
AGGREGATE
работает точно так же, как и встроенная функция
GROUP
, подобно SUM
или COUNT()
.
CREATE FUNCTION
сохраняет имя функции, тип и общедоступное
библиотечное имя в таблице mysql.func
системы. Вы должны иметь
привилегии insert и delete для базы данных
mysql
, чтобы создавать и удалять функции.
Все активные функции перезагружаются при каждом запуске сервера, если Вы не
запускаете mysqld
с опцией --skip-grant-tables
. В этом
случае инициализация пропущена, и UDF станут недоступны. Активная функция
представляет собой такую функцию, которая была загружена с помощью CREATE
FUNCTION
, но не была удалена через вызов DROP FUNCTION
.
Для работы
механизма UDF функции должны быть написаны на C или C++, Ваша операционная
система должна поддерживать динамическую загрузку, и mysqld
должен
быть откомпилирован динамически (не статически).
Для работы механизма UDF функции должны быть написаны на C или C++, а Ваша
операционная система должна поддерживать динамическую загрузку. Дистрибутив
исходников MySQL включает файл sql/udf_example.cc, который определяет 5
новых функций. Консультируйтесь с этим файлом, чтобы видеть, как работают
соглашения о вызовах 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'' используется для имени функции примера. Здесь XXX()
(верхний регистр) указывает SQL-обращение к функции, и xxx()
(нижний регистр) указывает C/C++-обращение к функции.
Функции, которые Вы пишете на C/C++ для реализации интерфейса с
XXX()
:
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()
, так что
она может выполнить требуемую очистку.
Все функции должны быть безопасны для потоков (не только основная функция, но
и остальные: инициализация и деинициализация идут в поточном режиме!). Это
означает, что Вам не позволят распределить любые глобальные или менять
статические переменные! Если Вы нуждаетесь в памяти, Вы должны распределить ее в
xxx_init()
и непременно освободить в xxx_deinit()
.
Основная функция должна быть объявлена как показано ниже. Обратите внимание,
что тип возврата и параметры отличаются в зависимости от того, объявите ли Вы
тип возврата функции SQL XXX()
как STRING
,
INTEGER
или REAL
в вызове CREATE
FUNCTION
:
Для функций типа STRING
:
char *xxx(UDF_INIT *initid, UDF_ARGS *args, char *result,
unsigned long *length, char *is_null, char *error);
Для функций типа INTEGER
:
long long xxx(UDF_INIT *initid, UDF_ARGS *args,
char *is_null, char *error);
Для функций типа REAL
:
double xxx(UDF_INIT *initid, UDF_ARGS *args,
char *is_null, char *error);
Функции инициализации и деинициализации объявлены подобно этому:
my_bool xxx_init(UDF_INIT *initid,
UDF_ARGS *args, char *message);
void xxx_deinit(UDF_INIT *initid);
Параметр initid
передан всем трем функциям. Он указывает на
структуру UDF_INIT
, которая используется, чтобы передать информацию
между функциями. Члены структуры UDF_INIT
перечислены ниже. Функция
инициализации должна заполнить любые члены, которые она желает изменить. Чтобы
использовать значение по умолчанию для члена, оставьте его неизменным. Перейдем
к описанию:
my_bool maybe_null
xxx_init()
должна установить maybe_null
в
1
, если xxx()
может возвращать NULL
.
Значение по умолчанию 1
, если любой из параметров объявлен как
maybe_null
.
unsigned int decimals
- Число десятичных цифр. Значение по умолчанию: максимальное количество
десятичных цифр в параметрах, переданных основной функции. Например, если
функции переданы
1.34
, 1.345
и 1.3
,
значением по умолчанию будет 3, поскольку 1.345
имеет 3
десятичных цифры.
unsigned int max_length
- Максимальная длина результата-строки. Значение по умолчанию отличается в
зависимости от типа результата функции. Для строчных функций значение по
умолчанию равно длине самого длинного параметра. Для целочисленных функций
значение по умолчанию соответствует 21 цифре. Для реальных функций значение по
умолчанию 13+количество десятичных чисел, обозначенных как
initid->decimals
. Для числовых функций длина включает любой
знак или десятичные символы отметки.
char *ptr
- Указатель, который функция может использовать для собственных целей.
Например, функции могут использовать
initid->ptr
, чтобы
передать распределенную память между функциями. В xxx_init()
как
обычно распределите память и назначьте ее этому указателю: initid->ptr=allocated_memory;
В xxx()
и xxx_deinit()
обратитесь к
initid->ptr
, чтобы использовать или освободить память.
Параметр args
указывает на структуру UDF_ARGS
,
члены которой приведены ниже:
unsigned int arg_count
- Число параметров. Проверьте это значение в функции инициализации, если Вы
хотите, чтобы Ваша функция была вызвана со специфическим числом параметров.
Например, таким кодом:
if (args->arg_count != 2)
{
strcpy(message,"XXX() requires two arguments");
return 1;
}
enum Item_result *arg_type
- Типы для каждого параметра. Возможные значения типов:
STRING_RESULT
, INT_RESULT
и
REAL_RESULT
. Чтобы удостовериться, что параметры имеют данный тип
и возвращают ошибку, если они к нему не принадлежат, проверьте массив
arg_type
в функции инициализации. Например: if (args->arg_type[0] != STRING_RESULT ||
args->arg_type[1] != INT_RESULT)
{
strcpy(message,"XXX() requires a string and an integer");
return 1;
}
Вы можете использовать функцию инициализации, чтобы установить элементы
arg_type
к типам, которые Вы хотите получить. Это заставляет
MySQL привести параметры к тем типам для каждого обращения к
xxx()
. Например, чтобы определить первые два элемента как строку
и число, сделайте следующее в xxx_init()
: args->arg_type[0] = STRING_RESULT;
args->arg_type[1] = INT_RESULT;
char **args
args->args
сообщает информацию функции инициализации
относительно общего характера параметров, с которыми Ваша функция была
вызвана. Для постоянного параметра (константы) i
args->args[i]
указывает на значение параметра. Для
непостоянного параметра args->args[i]
равно 0
.
Постоянный параметр представляет собой выражение, которое использует только
константы, типа 3
, 4*7-2
или SIN(3.14)
.
Непостоянный параметр представляет собой выражение, которое обращается к
значениям, которые могут изменяться, типа имени столбца или функций, которые
вызваны с непостоянными параметрами. Для каждого обращения основной функции
args->args
хранит фактические параметры, которые переданы для
в настоящее время обрабатываемой строки. Функции могут обратиться к параметру
i
следующим образом:
unsigned long *lengths
- Для функции инициализации, массив
lengths
указывает
максимальную длину строки для каждого параметра. Для каждого обращения к
основной функции lengths
хранит фактические длины любых строковых
параметров, которые переданы для строки, обрабатываемой в настоящее время. Для
параметров типов INT_RESULT
или REAL_RESULT
lengths
хранит максимальную длину параметра (как для функции
инициализации).
Функция инициализации возвратит 0
, если никакая ошибка не
произошла, и 1
в противном случае. Если ошибка происходит,
xxx_init()
должна сохранить сообщение об ошибке с нулевым символом
в конце в параметре message
. Сообщение будет возвращено
пользователю. Буфер сообщений имеет длину в MYSQL_ERRMSG_SIZE
символов, но Вы должны попробовать сохранить сообщение в 80 символах так, чтобы
это удовлетворило ширине стандартного экрана терминала.
Значение возврата основной функции xxx()
зависит от типа. Для
функций типов long long
и double
оно представляет
собой собственно функциональное значение. Строковые функции должны возвратить
указатель на результат и сохранить длину строки в параметрах
length
. Здесь result
представляет собой буфер длиной в
255 байт. Установите их к содержанию и длине значения. Например:
memcpy(result, "result string", 13);
*length=13;
Если Ваши функции строки должны возвратить строку длиннее, чем 255 байт,
распределите память для результата через malloc()
в функции
xxx_init()
или в xxx()
, а затем освободите память в
xxx_deinit()
. Вы можете сохранять распределенную память в слоте
ptr
структуры UDF_INIT
для повторного использования в
будущем обращении xxx()
.
Чтобы указывать значение возврата NULL
в основной функции,
установите is_null
в 1
:
*is_null=1;
Чтобы указать возврат ошибки в основной функции, установите параметр ошибки
(error
) в значение 1
:
*error=1;
Если xxx()
устанавливает *error
в 1
для любой строки, функциональное значение NULL
для текущей строки и
для любых последующих строк, обработанных инструкцией, в которой вызывалась
XXX()
. Причем, xxx()
не будет даже запрашиваться для
последующих строк. ПРИМЕЧАНИЕ: В MySQL до версии 3.22.10 Вы
должны установить *error
и *is_null
:
*error=1;
*is_null=1;
Файлы, выполняющие UDF, должны компилироваться и устанавливаться на сервере.
Этот процесс описан ниже для примерного UDF-файла udf_example.cc,
который включен в дистрибутив исходников MySQL. Этот файл содержит следующие
функции:
metaphon()
возвращает мета-строку для строкового параметра.
Это похоже на soundex, но больше заточено под английский.
myfunc_double()
возвращает сумму ASCII-значений символов в
параметрах, поделенную на сумму длин этих параметров.
myfunc_int()
возвращает сумму длин параметров.
sequence([const int])
возвратит последовательность,
начинающуюся с заданного числа или с 1, если никакого числа задано не было.
lookup()
возвращает IP-адрес.
reverse_lookup()
возвращает hostname для IP-адреса. Функция
может быть вызвана со строкой "xxx.xxx.xxx.xxx"
или с 4 числами.
Динамически загружаемый файл должен компилироваться как разделяемый объектный
файл, используя команду:
shell> gcc -shared -o udf_example.so myfunc.cc
Вы можете легко выяснять правильные параметры компилятора для Вашей системы,
запуская такую команду в каталоге sql Вашего дерева исходных текстов
MySQL:
shell> make udf_example.o
Вы должны выполнить команду компиляции, подобную одной из тех, что отображает
make
, за исключением того, что Вы должны удалить опцию
-c
близко к концу строки и добавить -o udf_example.so
в самый конец строки. На некоторых системах удалять -c
не надо,
пробуйте.
Как только Вы скомпилируете общедоступный объект, содержащий UDF, Вы должны
установить его и сообщить MySQL о расширении функциональности. Компиляция
общедоступного объекта из udf_example.cc производит файл с именем
udf_example.so (точное имя может изменяться от платформы к платформе).
Скопируйте этот файл в некоторый каталог, где ищет файлы ld
,
например, в /usr/lib. На многих системах Вы можете устанавливать
системную переменную LD_LIBRARY
или LD_LIBRARY_PATH
,
чтобы указать каталог, где Вы имеете Ваши файлы функции UDF. Руководство на
dlopen
сообщает Вам, которую переменную Вы должны использовать на
Вашей системе. Вы должны установить это в mysql.server
или в
safe_mysqld
и перезапустить mysqld
.
После того, как библиотека установлена, сообщите mysqld
относительно новых функций этими командами:
mysql> CREATE FUNCTION metaphon RETURNS STRING SONAME "udf_example.so";
mysql> CREATE FUNCTION myfunc_double RETURNS REAL SONAME
"udf_example.so";
mysql> CREATE FUNCTION myfunc_int RETURNS INTEGER SONAME
"udf_example.so";
mysql> CREATE FUNCTION lookup RETURNS STRING SONAME "udf_example.so";
mysql> CREATE FUNCTION reverse_lookup RETURNS STRING SONAME
"udf_example.so";
Функции могут быть удалены, используя DROP FUNCTION
:
mysql> DROP FUNCTION metaphon;
mysql> DROP FUNCTION myfunc_double;
mysql> DROP FUNCTION myfunc_int;
mysql> DROP FUNCTION lookup;
mysql> DROP FUNCTION reverse_lookup;
Инструкции CREATE FUNCTION
и DROP FUNCTION
модифицируют системную таблицу func
в базе данных
mysql
. Имя функции, тип и общедоступное библиотечное имя будут
сохранено в таблице. Вы должны иметь привилегии insert и
delete для базы данных mysql
, чтобы создавать и
удалять свои функции.
Вы не должны использовать CREATE FUNCTION
, чтобы добавить
функцию, которая уже была создана. Если Вы должны повторно установить функцию,
сначала удалите ее через вызов DROP FUNCTION
и затем повторно
установите ее с помощью CREATE FUNCTION
. Вы должны сделать это,
например, если Вы откомпилировали новую версию Вашей функции, чтобы
mysqld
обновил используемую им версию. Иначе сервер продолжит
применять старую версию.
Активные функции будут перезагружены при каждом перезапуске сервера, если Вы
не запускаете mysqld
с опцей --skip-grant-tables
. В
этом случае инициализация UDF будет пропущена, а UDF-функции станут
недоступными. Активная функция представляет собой функцию, загруженную через
CREATE FUNCTION
, но не удаленную DROP FUNCTION
.
Процедура для добавления новой встроенной функции описана ниже. Обратите
внимание, что Вы не можете добавлять встроенные функции к двоичному дистрибутиву
потому, что процедура включает изменение исходного текста MySQL. Вы должны
скомпилировать MySQL самостоятельно из исходников. Также обратите внимание, что,
если Вы мигрируете на другую версию MySQL (например, когда новая версия
выпущена), Вы будете должны повторить процедуру с новой версией.
Чтобы добавить новую встроенную функцию MySQL, нужно:
- Добавьте одну строку в файл lex.h, которая определяет имя функции
в массиве
sql_functions[]
.
- Если функциональный прототип прост (берет не более трех параметров), Вы
должны в lex.h определить SYM(FUNC_ARG#) (здесь # является числом параметров)
как второй параметр в массиве
sql_functions[]
и добавить функцию,
которая создает функциональный объект, в 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
в качестве типичного примера
того, как все это сделать.
Все функции должны быть поточно-безопасными (другими словами, не используйте
любые глобальные или статические переменные в функциях без того, чтобы защитить
их через mutex).
Если Вы хотите возвращать NULL
из ::val()
,
::val_int()
или ::str()
Вы должны установить
null_value
в 1 и вернуть из функции 0.
Для объектной функции ::str()
имеются некоторые дополнительные
хитрости, которые надо знать:
- Параметр
String *str
обеспечивает буфер строки, который может
использоваться, чтобы хранить результат. Для получения большего количества
информации относительно типа String
обратитесь к файлу
sql_string.h.
- Функция
::str()
должна возвратить строку, которая хранит
результат, или (char*) 0
, если результатом является
NULL
.
- Все текущие функции строки не должны распределять никакую память, если это
не абсолютно необходимо!
В MySQL Вы можете определять процедуру на C++, которая может обращаться и
изменять данные в запросе прежде, чем они отправятся к пользователю. Модификация
может быть выполнена на уровне строки или GROUP BY
.
Авторы пакета создали процедуру примера в MySQL Version 3.23, чтобы показать
Вам, что там может быть выполнено.
Дополнительно авторы рекомендуют Вам посмотреть файл mylua, который Вы можете
найти в каталоге Contrib. Вы можете использовать язык LUA, чтобы загрузить
процедуру в mysqld
прямо во время выполнения.
analyse([max elements,[max memory]])
Эта процедура определена в sql/sql_analyse.cc. Она исследует
результат, полученный из Вашего запроса, и возвращает анализ результатов:
max elements
(по умолчанию 256) задает максимальное число
разных значений, которые analyse
заметит в столбце. Это
используется, чтобы проверить оптимальность применения типа ENUM
.
max memory
(по умолчанию 8192) задает максимум памяти,
которую analyse
должен распределить на столбец при попытке найти
все отличные значения.
SELECT ... FROM ... WHERE ... PROCEDURE
ANALYSE([max elements,[max memory]])
9.2.2 Написание процедур
На сегодняшний день единственной документацией для этого является исходный
код пакета.
Вы можете найти всю информацию относительно процедур, исследуя файлы:
- sql/sql_analyse.cc
- sql/procedure.h
- sql/procedure.cc
- sql/sql_select.cc
Эта глава описывает много вещей, которые Вы должны знать при работе на коде
MySQL. Если Вы планируете способствовать MySQL разработке, иметь доступ к коду
отлаживаемых версий или хотите только следить за разработкой, поставьте дерево
исходников для разработки. Если Вы заинтересованы внутренней организацией MySQL,
Вы должны также подписаться на специальный список рассылки internals@lists.mysql.com.
Сервер MySQL создает следующие потоки:
- Поток TCP/IP-подключений обрабатывает все подключения, запрашивает и
создает новый специализированный поток, чтобы обработать авторизацию и запросы
SQL для каждого подключения.
- В Windows NT имеется драйвер именованного канала, который делает ту же
самую работу, что и поток TCP/IP, но с запросами на именованном канале.
- Поток сигнала обрабатывает все сигналы. Он также обычно обрабатывает
тревоги и вызывает
process_alarm()
, чтобы завершить подключения,
которые были неактивны слишком долго.
- Если
mysqld
компилируется с -DUSE_ALARM_THREAD
,
специализированный поток, который обрабатывает тревоги, будет создан. Это
используется только на некоторых системах, где имеются проблемы с
sigwait()
, или если есть недостатки в применении кода
thr_alarm()
в прикладной программе без специализированного потока
обработки сигнала.
- Если использована опция
--flush_time=#
, будет создан еще один
специализированный поток, который сбрасывает таблицы на диск.
- Каждое соединение обрабатывается своим потоком.
- Каждая таблица, на которой использована инструкция
INSERT
DELAYED
, получает собственный поток.
- Если Вы используете
--master-host
, будет запущен поток
репликации, чтобы читать и применять модификации с главного сервера.
mysqladmin processlist
показывает только подключения, потоки
репликации и INSERT DELAYED
.
До недавнего времени основной набор теста был основан на составляющих
собственность данных заказчика и по этой причине не был публично доступен.
Единственный публично доступная часть процесса тестирования состояла из теста
crash-me
, эталонного теста Perl DBI/DBD, находящегося в каталоге
sql-bench
, и разнообразных тестов, размещенных в каталоге
tests
. Отсутствие стандартизированного публично доступного набора
тестов сделало трудным для пользователей и разработчиков тестирование кода
MySQL. Чтобы исправить эту ситуацию, авторы пакета создали совершенно новую
систему тестов, которая теперь включена в исходные и двоичные дистрибутивы,
начиная с Version 3.23.29.
Текущий набор тестов не проверяет все в MySQL, но должен охватить наиболее
очевидные ошибки в обработка кода SQL, OS/library проблемы и тестирование
репликации. Конечная цель состоит в том, чтобы иметь тесты, покрывающие 100%
кода. Вы можете предоставить тесты, которые исследуют функциональные
возможности, критичные для Вашей системы, поскольку это гарантирует, что все
будущие выпуски MySQL будут хорошо работать с Вашими прикладными программами.
Система теста состоит из интерпретатора языков тестов
(mysqltest
), скрипта оболочки, чтобы выполнить все тесты
(mysql-test-run
), фактических случаев тестов, написанных на
специальном языке тестов и их ожидаемых результатов. Чтобы выполнить набор теста
на Вашей системе после построения, введите make test
или
mysql-test/mysql-test-run
из корневого каталога исходных текстов.
Если Вы установили двоичный дистрибутив, перейдите в корень установки (например,
/usr/local/mysql
) и скомандуйте
scripts/mysql-test-run
. Все тесты должны выполниться. Если этого не
произошло, пропобуйте выяснить почему и сообщите о проблеме, если это ошибка в
пакете MySQL.
Если Вы имеете копию mysqld
на машине, где Вы хотите выполнить
набор тестов, Вы не должны останавливать ее, если она не использует порты
9306
и 9307
. Если один из этих портов применяется, Вы
должны отредактировать mysql-test-run
и изменить значения главного
или подчиненного порта к тому, которое является доступным.
Вы можете запустить индивидуально каждый тест командой
mysql-test/mysql-test-run test_name
.
Если один тест свалился, проверьте работу mysql-test-run
с
опцией --force
, чтобы проверить, сбоят ли любые другие тесты.
Вы можете использовать язык mysqltest
, чтобы писать Ваши
собственные случаи теста. К сожалению, авторы пакета еще не написали полную
документацию для него. Вы можете, однако, рассматривать текущие случаи теста и
использовать их как пример. Следующие пункты должны помочь Вам:
Если Ваша версия MySQL не выполняет набор тестов, Вы должны сделать так:
содержание назад вперед