Могу ли я написать UDF для MySQL на Python?

#python #mysql #user-defined-functions

#python #mysql #определяемые пользователем функции

Вопрос:

Я хотел бы иметь возможность вызывать Python через хранимые процедуры MySQL.
По этой причине мне было интересно, могу ли я использовать Python для написания UDF, который я могу вызывать из MySQL.

Если это невозможно, какой альтернативный способ я мог бы использовать, чтобы это произошло.

Ответ №1:

В документах MySQL 5.0 говорится, что триггер может вызывать UDF, так что эта часть кажется возможной. Просмотр исходного кода некоторых расширений UDF даст вам хорошее представление о сложности. Вы можете найти пакеты с открытым исходным кодом в репозитории UDF MySQL.

Хотелось бы, чтобы у меня был простой ответ на часть «создать UDF MySQL на Python», но я не знаю простого готового способа сделать это.

В Postgres есть язык PL / Python, который позволяет вам писать процедуры и функции непосредственно с использованием Python внутри базы данных. Этот код может быть лучшим руководством для выяснения того, как подключить Python к MySQL; однако, насколько мне известно, никто этого еще не сделал (но я бы хотел ошибаться).

Несколько запутанных деталей о том, как это может быть сделано:

UDF — это общие объекты, которые загружаются в демон MySQL, поэтому для его создания вам нужно иметь возможность генерировать заглушки C, которые (среди прочего) инициализируют интерпретатор Python, загружают и компилируют ваш скрипт Python в байт-код, а затем переводят аргументы UDF MySQL в вызов функции Python, а затем переводят возвращаемое значение обратно.

Для простой строковой функции UDF с именем myfunc общий объект будет иметь следующие функции:

 // initialize state when 'myfunc' is loaded.
my_bool myfunc_init(UDF_INIT *initid, UDF_ARGS *args, ...)

// call myfunc, this would need to translate the args, invoke the
// python function, then return the string, may need to create and cache
// python sub-interpreters on the fly, etc
char *myfunc(UDF_INIT *initid, UDF_ARGS *args, ...)

// clean up the state when 'myfunc' is unloaded.
void myfunc_deinit(UDF_INIT *initid);
  

Поскольку может быть несколько вызовов вашего UDF, выполняемых одновременно на отдельных
потоки, поэтому вам нужно будет найти
способ эффективного создания и кэширования субинтерпретаторов по требованию внутри
контекст одного вызова функции или безопасное повторное использование одного интерпретатора
в нескольких потоках (с блокировкой, которая может неприемлемо замедлить работу).