擴展 MySQL 9.0  /  新增函數到 MySQL  /  新增原生函數

6.1 新增原生函數

要新增原生 MySQL 函數,請使用此處描述的程序,該程序要求您使用原始碼散佈。您無法將原生函數新增到二進位散佈,因為必須修改 MySQL 原始碼並從修改後的原始碼編譯 MySQL。如果您遷移到另一個版本的 MySQL(例如,當新版本發佈時),您必須使用新版本重複該程序。

如果原生函數將在將複製到複本的陳述式中被引用,您必須確保每個複本也都有該函數可用。否則,當複本嘗試調用該函數時,複製將會在複本上失敗。

要新增原生函數,請按照以下步驟修改 sql 目錄中的原始碼檔案

  1. item_create.cc 中為該函數建立一個子類別

    • 如果該函數接受固定數量的引數,請分別建立 Create_func_arg0Create_func_arg1Create_func_arg2Create_func_arg3 的子類別,具體取決於該函數是否接受零個、一個、兩個或三個引數。如需範例,請參閱 Create_func_uuidCreate_func_absCreate_func_powCreate_func_lpad 類別。

    • 如果該函數接受可變數量的引數,請建立 Create_native_func 的子類別。如需範例,請參閱 Create_func_concat

  2. 為了提供 SQL 陳述式中可以引用該函數的名稱,請透過在 item_create.cc 中將一行新增到此陣列來註冊該名稱

    static Native_func_registry func_array[]

    您可以為同一函數註冊多個名稱。例如,請參閱 "LCASE""LOWER" 的行,它們是 Create_func_lcase 的別名。

  3. item_func.h 中,宣告一個從 Item_num_funcItem_str_func 繼承的類別,具體取決於您的函數是傳回數字還是字串。

  4. 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() 函數,該函數對 ::str() 傳回的值執行 atof()

  5. 如果函數是不確定的,請在項目建構函式中加入以下陳述式,以指示不應快取函數結果

    current_thd->lex->safe_to_cache_query=0;

    如果函數的引數值固定,但不同調用可能會傳回不同的結果,則該函數是不確定的。

  6. 您可能也應該定義以下物件函數

    void Item_func_newname::fix_length_and_dec()

    此函數至少應根據給定的引數計算 max_lengthmax_length 是函數可能傳回的最大字元數。如果主函數不能傳回 NULL 值,此函數也應設定 maybe_null = 0。該函數可以透過檢查引數的 maybe_null 變數來檢查任何函數引數是否可以傳回 NULL。請參閱 Item_func_mod::fix_length_and_dec,以取得如何執行此操作的典型範例。

所有函數都必須是執行緒安全的。換句話說,請勿在函數中使用任何全域或靜態變數,而不使用互斥鎖保護它們。

如果您想從 ::val()::val_int()::str() 傳回 NULL,您應該將 null_value 設定為 1 並傳回 0。

對於 ::str() 物件函數,以下額外注意事項適用

  • String *str 引數提供可用於保存結果的字串緩衝區。(如需有關 String 類型的詳細資訊,請查看 sql_string.h 檔案。)

  • ::str() 函數應傳回保存結果的字串,如果結果為 NULL,則傳回 (char*) 0

  • 目前所有字串函數都會嘗試避免分配任何記憶體,除非絕對必要!