日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

十分钟成为 TiDB Contributor,还送限量版马克杯

發布時間:2025/3/21 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 十分钟成为 TiDB Contributor,还送限量版马克杯 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

2019獨角獸企業重金招聘Python工程師標準>>>

背景知識

SQL 語句發送到 TiDB 后首先會經過 parser,從文本 parse 成為 AST(抽象語法樹),通過 Query Optimizer 生成執行計劃,得到一個可以執行的 plan,通過執行這個 plan 即可得到結果,這期間會涉及到如何獲取 table 中的數據,如何對數據進行過濾、計算、排序、聚合、濾重以及如何對表達式進行求值。 對于一個 builtin 函數,比較重要的是進行語法解析以及如何求值。其中語法解析部分需要了解如何寫 yacc 以及如何修改 TiDB 的詞法解析器,較為繁瑣,我們已經將這部分工作提前做好,大多數 builtin 函數的語法解析工作已經做完。 對 builtin 函數的求值需要在 TiDB 的表達式求值框架下完成,每個 builtin 函數被認為是一個表達式,用一個 ScalarFunction 來表示,每個 builtin 函數通過其函數名以及參數,獲取對應的函數類型以及函數簽名,然后通過函數簽名進行求值。 總體而言,上述流程對于不熟悉 TiDB 的朋友而言比較復雜,我們對這部分做了些工作,將一些流程性、較為繁瑣的工作做了統一處理,目前已經將大多數未實現的 buitlin 函數的語法解析以及尋找函數簽名的工作完成,但是函數實現部分留空。換句話說,只要找到留空的函數實現,將其補充完整,即可作為一個 PR。

添加 builtin 函數整體流程

  • 找到未實現的函數 在 TiDB 源碼中的 expression 目錄下搜索 errFunctionNotExists,即可找到所有未實現的函數,從中選擇一個感興趣的函數,比如 SHA2 函數:
func (b *builtinSHA2Sig) eval(row []types.Datum) (d types.Datum, err error) {return d, errFunctionNotExists.GenByArgs("SHA2") }
  • 實現函數簽名 接下來要做的事情就是實現 eval 方法,函數的功能請參考 MySQL 文檔,具體的實現方法可以參考目前已經實現函數。

  • 在 typeinferer 中添加類型推導信息 在 plan/typeinferer.go 中的 handleFuncCallExpr() 里面添加這個函數的返回結果類型,請保持和 MySQL 的結果一致。全部類型定義參見 MySQL Const。

* 注意大多數函數除了需要填寫返回值類型之外,還需要獲取返回值的長度。
  • 寫單元測試 在 expression 目錄下,為函數的實現增加單元測試,同時也要在 plan/typeinferer_test.go 文件中添加 typeinferer 的單元測試

  • 運行 make dev,確保所有的 test case 都能跑過

示例

這里以新增 SHA1() 函數的 PR 為例,進行詳細說明 首先看 expression/builtin_encryption.go: 將 SHA1() 的求值方法補充完整

func (b *builtinSHA1Sig) eval(row []types.Datum) (d types.Datum, err error) {// 首先對參數進行求值,這塊一般不用修改args, err := b.evalArgs(row)if err != nil {return types.Datum{}, errors.Trace(err)}// 每個參數的意義請參考 MySQL 文檔// SHA/SHA1 function only accept 1 parameterarg := args[0]if arg.IsNull() {return d, nil}// 這里對參數值做了一個類型轉換,函數的實現請參考 util/types/datum.gobin, err := arg.ToBytes()if err != nil {return d, errors.Trace(err)}hasher := sha1.New()hasher.Write(bin)data := fmt.Sprintf("%x", hasher.Sum(nil))// 設置返回值d.SetString(data)return d, nil }

接下來給函數實現添加單元測試,參見 expression/builtin_encryption_test.go:

var shaCases = []struct {origin interface{}crypt string}{{"test", "a94a8fe5ccb19ba61c4c0873d391e987982fbbd3"},{"c4pt0r", "034923dcabf099fc4c8917c0ab91ffcd4c2578a6"},{"pingcap", "73bf9ef43a44f42e2ea2894d62f0917af149a006"},{"foobar", "8843d7f92416211de9ebb963ff4ce28125932878"},{1024, "128351137a9c47206c4507dcf2e6fbeeca3a9079"},{123.45, "22f8b438ad7e89300b51d88684f3f0b9fa1d7a32"},}func (s *testEvaluatorSuite) TestShaEncrypt(c *C) {defer testleak.AfterTest(c)() // 監測 goroutine 泄漏的工具,可以直接照搬fc := funcs[ast.SHA]for _, test := range shaCases {in := types.NewDatum(test.origin)f, _ := fc.getFunction(datumsToConstants([]types.Datum{in}), s.ctx)crypt, err := f.eval(nil)c.Assert(err, IsNil)res, err := crypt.ToString()c.Assert(err, IsNil)c.Assert(res, Equals, test.crypt)}// test NULL input for shavar argNull types.Datumf, _ := fc.getFunction(datumsToConstants([]types.Datum{argNull}), s.ctx)crypt, err := f.eval(nil)c.Assert(err, IsNil)c.Assert(crypt.IsNull(), IsTrue) } * 注意,除了正常 case 之外,最好能添加一些異常的case,如輸入值為 nil,或者是多種類型的參數

最后還需要添加類型推導信息以及 test case,參見 plan/typeinferer.go,plan/typeinferer_test.go:

case ast.SHA, ast.SHA1:tp = types.NewFieldType(mysql.TypeVarString)chs = v.defaultCharsettp.Flen = 40 {`sha1(123)`, mysql.TypeVarString, "utf8"},{`sha(123)`, mysql.TypeVarString, "utf8"},

編輯按:添加 TiDB Robot 微信,加入 TiDB Contributor Club,無門檻參與開源項目,改變世界從這里開始吧(萌萌噠)。

聽說現在成為 TiDB Contributor 就送限量版馬克杯呦~

轉載于:https://my.oschina.net/zhaiyuan/blog/859106

總結

以上是生活随笔為你收集整理的十分钟成为 TiDB Contributor,还送限量版马克杯的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。