{"id":121,"date":"2018-08-03T00:00:00","date_gmt":"2018-08-03T00:00:00","guid":{"rendered":"https:\/\/en.pingcap.com\/blog\/adding-built-in-functions-to-tikv\/"},"modified":"2024-03-18T06:31:29","modified_gmt":"2024-03-18T13:31:29","slug":"adding-built-in-functions-to-tikv","status":"publish","type":"post","link":"https:\/\/www.pingcap.com\/ko\/blog\/adding-built-in-functions-to-tikv\/","title":{"rendered":"Landing Your First Rust Pull Request in TiKV"},"content":{"rendered":"<p><em>Note: This post is out of date.<\/em><\/p>\n<p>This guide is intended to show how you can land your first Pull Request (PR) in Rust to contribute to TiKV in less than 30 minutes. But before we do that, here&#8217;s some helpful background.<\/p>\n<p><a href=\"https:\/\/github.com\/pingcap\/tidb\">TiDB<\/a> (&#8220;Ti&#8221; = Titanium) is an open-source distributed scalable Hybrid Transactional and Analytical Processing (<a href=\"https:\/\/en.wikipedia.org\/wiki\/Hybrid_transactional\/analytical_processing_(HTAP)\">HTAP<\/a>) database, built by the company PingCAP (that&#8217;s us!) and its active open-source community (that&#8217;s you!). It&#8217;s designed to provide infinite horizontal scalability, strong consistency, and high availability with MySQL compatibility. It serves as a one-stop data warehouse for both OLTP (Online Transactional Processing) and OLAP (Online Analytical Processing) workloads.<\/p>\n<p>What powers this experience is <a href=\"https:\/\/github.com\/pingcap\/tikv\">TiKV<\/a>, a distributed transactional key-value store (all built in Rust!), which is now deployed in more than 200 companies in production. One key reason why TiDB can process complex SQL queries so quickly is a Coprocessor API layer between TiDB and TiKV, which takes advantage of the distributed nature of a distributed database to &#8220;push down&#8221; partial queries in parallel, where partial results are generated and reassembled for the client. This is a key differentiator between TiDB and other distributed databases.<\/p>\n<p>So far, TiDB can only push down some simple expressions to TiKV to be processed, e.g. fetching the value in a column and doing comparison or arithmetic operations on simple data structures. To get more juice out of distributed computing resources, we need to include more expressions to push down. The first type is MySQL built-in functions. How do we accomplish that in short order? That&#8217;s where <em>you<\/em>&#8211;our intrepid systems hacker, Rust lover, and distributed system geek&#8211;come in!<\/p>\n<p>So follow along this guide to contribute a built-in MySQL function to TiKV in Rust in 30 minutes. And when you do, you will receive some special gifts from us reserved just for our beloved contributors, as a small token of our gratitude. Let&#8217;s get started!<\/p>\n<h2>How the Coprocessor Works<\/h2>\n<p>Before diving into our step-by-step guide on how to contribute, it&#8217;s worth understanding how TiDB&#8217;s Coprocessor works at a high-level. After TiDB receives a SQL statement, it parses the statement into an abstract syntax tree (AST), then generates an optimal execution plan using its Cost-Based Optimizer. (Learn more details on how TiDB generates a query plan <a href=\"https:\/\/docs.pingcap.com\/tidb\/stable\/explain-overview\">HERE<\/a>.) The execution plan is split into multiple subtasks and the Coprocessor API pushes down these subtasks to different TiKV nodes to be processed in parallel.<\/p>\n<p>Here&#8217;s an illustration on how a statement like <code>select count(*) from t where a + b &gt; 5<\/code> gets pushed down:<\/p>\n<p>After TiKV receives these subtask expressions, the following steps are performed in a loop:<\/p>\n<ol>\n<li>Obtain the complete data of the next row, parse and decode the data record based on the requested columns.<\/li>\n<li>Use the predicate specified in the <code>where<\/code> clause to filter data.<\/li>\n<li>If the data passes the filter predicate, the aggregation result will be computed.<\/li>\n<\/ol>\n<p>After different TiKV nodes compute and return results of their respective subtasks, they are returned to TiDB. TiDB then aggregates on all the results sent from TiKV and sends the final result to the client.<\/p>\n<h2>How to add a MySQL built-in function to TiKV<\/h2>\n<p>Now that you have an overview of how Coprocessor in TiDB\/TiKV works, here&#8217;s how to contribute MySQL built-in functions to further strengthen TiKV&#8217;s coprocessing power!<\/p>\n<h3>Step 1: Select a function for pushdown<\/h3>\n<p>Go to the <a href=\"https:\/\/github.com\/pingcap\/tikv\/issues\/3275\"><code>push down scalar functions<\/code> issue page<\/a>, choose a function you like from the unimplemented function signature list, then tell us so we can create an issue and assign it to you to prevent duplication of work.<\/p>\n<h3>Step 2: Find the logic of corresponding implementation in TiDB<\/h3>\n<p>Search the related <code>builtinXXXSig<\/code> (XXX is the function signature you want to implement) in the <code>expression<\/code> directory of TiDB.<\/p>\n<p>Take <a href=\"https:\/\/github.com\/pingcap\/tikv\/pull\/3277\"><code>MultiplyIntUnsigned<\/code><\/a> as an example, which we will use throughout this guide, you can find the corresponding function signature (<code>builtinArithmeticMultiplyIntUnsignedSig<\/code>) and its implementation.<\/p>\n<h3>Step 3: Define the function<\/h3>\n<ol>\n<li>The name of the file where the built-in function exists in TiKV should correspond to the same name in TiDB.For example, since all the pushdown files in the <code>expression<\/code> directory in TiDB are named <code>builtin_XXX<\/code>, in TiKV the corresponding file name should be <code>builtin_XXX.rs<\/code>. In this example, the current function is in the builtin_arithmetic.go file in TiDB, so the function should be placed in builtin_arithmetic.rs in TiKV.<strong>Note:<\/strong> If the corresponding file in TiKV does not exist, you need to create a new file in the corresponding directory with the same name as in TiDB.<\/li>\n<li>The function name should follow the Rust snake_case naming conventions.For this example, <code>MultiplyIntUnsigned<\/code> will be defined as <code>multiply_int_unsigned<\/code>.<\/li>\n<li>For the return value, you can refer to the <code>Eval<\/code> functions which are implemented in TiDB and their corresponding return value types, as shown in the following table:<br \/>\n<table style=\"border-collapse: collapse; width: 100%; height: 280px;\">\n<tbody>\n<tr style=\"height: 35px;\">\n<td style=\"width: 50%; height: 35px;\"><strong><code>Eval<\/code> Function in TiDB<\/strong><\/td>\n<td style=\"width: 50%; height: 35px;\"><strong>Return Value Type in TiKV<\/strong><\/td>\n<\/tr>\n<tr style=\"height: 35px;\">\n<td style=\"width: 50%; height: 35px;\">evalInt<\/td>\n<td style=\"width: 50%; height: 35px;\"><code>Result&lt;Option&lt;i64&gt;&gt;<\/code><\/td>\n<\/tr>\n<tr style=\"height: 35px;\">\n<td style=\"width: 50%; height: 35px;\">evalReal<\/td>\n<td style=\"width: 50%; height: 35px;\"><code>Result&lt;Option&lt;i64&gt;&gt;<\/code><\/td>\n<\/tr>\n<tr style=\"height: 35px;\">\n<td style=\"width: 50%; height: 35px;\">evalString<\/td>\n<td style=\"width: 50%; height: 35px;\"><code>Result&lt;Option&lt;Cow&lt;'a, [u8]&gt;&gt;&gt;<\/code><\/td>\n<\/tr>\n<tr style=\"height: 35px;\">\n<td style=\"width: 50%; height: 35px;\">evalDecimal<\/td>\n<td style=\"width: 50%; height: 35px;\"><code>Result&lt;Option&lt;Cow&lt;'a, Decimal&gt;&gt;&gt;<\/code><\/td>\n<\/tr>\n<tr style=\"height: 35px;\">\n<td style=\"width: 50%; height: 35px;\">evalTime<\/td>\n<td style=\"width: 50%; height: 35px;\"><code>Result&lt;Option&lt;Cow&lt;'a, Time&gt;&gt;&gt;<\/code><\/td>\n<\/tr>\n<tr style=\"height: 35px;\">\n<td style=\"width: 50%; height: 35px;\">evalDuration<\/td>\n<td style=\"width: 50%; height: 35px;\"><code> Result&lt;Option&lt;Cow&lt;'a, Duration&gt;&gt;&gt;<\/code><\/td>\n<\/tr>\n<tr style=\"height: 35px;\">\n<td style=\"width: 50%; height: 35px;\">evalJSON<\/td>\n<td style=\"width: 50%; height: 35px;\"><code>Result&lt;Option&lt;Cow&lt;'a, Json&gt;&gt;&gt;<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Thus, in TiDB&#8217;s <code>builtinArithmeticMultiplyIntUnsignedSig<\/code>, it implements the <code>evalInt<\/code> method, so the return value type of this function <code>multiply_int_unsigned<\/code> should be <code>Result&lt;Option&lt;i64&gt;&gt;<\/code>.<\/li>\n<li>All the arguments of the <code>builtin-in<\/code> function should be consistent with that of the <code>eval<\/code> function of the expression:\n<ul>\n<li>The statement context is <code>ctx:&amp;StatementContext<\/code><\/li>\n<li>The value of each column in this row is <code>row: &amp;[Datum]<\/code><\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<p>Putting all this together, the definition of the pushdown function <code>multiply_int_unsigned<\/code> should look like this:<\/p>\n<pre><code class=\"language-rust\">\n    pub fn multiply_int_unsigned(\n\n       &amp;self,\n\n       ctx: &amp;mut EvalContext,\n\n       row: &amp;[Datum],\n\n    ) -&gt; Result&lt;Option&lt;i64&gt;&gt;\n\n<\/code><\/pre>\n<h3>Step 4: Implement the function logic<\/h3>\n<p>Implement the function logic based on the corresponding logic in TiDB.<\/p>\n<p>For this example, you can see that the implementation of <code>builtinArithmeticMultiplyIntUnsignedSig<\/code> of TiDB is:<\/p>\n<pre><code class=\"language-go\">\nfunc (s *builtinArithmeticMultiplyIntUnsignedSig) evalInt(row types.Row) (val int64, isNull bool, err error) {\n\n  a, isNull, err := s.args[0].EvalInt(s.ctx, row)\n\n  if isNull || err != nil {\n\n     return 0, isNull, errors.Trace(err)\n\n  }\n\n  unsignedA := uint64(a)\n\n  b, isNull, err := s.args[1].EvalInt(s.ctx, row)\n\n  if isNull || err != nil {\n\n     return 0, isNull, errors.Trace(err)\n\n  }\n\n  unsignedB := uint64(b)\n\n  result := unsignedA * unsignedB\n\n  if unsignedA != 0 &amp;&amp; result\/unsignedA != unsignedB {\n\n     return 0, true, types.ErrOverflow.GenByArgs(\"BIGINT UNSIGNED\", fmt.Sprintf(\"(%s * %s)\", s.args[0].String(), s.args[1].String()))\n\n  }\n\n  return int64(result), false, nil\n\n}\n\n<\/code><\/pre>\n<p>To implement the same function in Rust for TiKV, it should be:<\/p>\n<pre><code class=\"language-rust\">pub fn multiply_int_unsigned(\n  &amp;self,\n  ctx: &amp;mut EvalContext,\n  row: &amp;[Datum],\n) -&gt; Result&lt;Option&lt;i64&gt;&gt; {\n  let lhs = try_opt!(self.children[0].eval_int(ctx, row));\n  let rhs = try_opt!(self.children[1].eval_int(ctx, row));\n  let res = (lhs as u64).checked_mul(rhs as u64).map(|t| t as i64);\n  \/\/ TODO: output expression in error when column's name pushed down.\n  res.ok_or_else(|| Error::overflow(\"BIGINT UNSIGNED\", &amp;format!(\"({} * {})\", lhs, rhs)))\n      .map(Some)\n}\n<\/code><\/pre>\n<h3>Step 5: Add argument check<\/h3>\n<p>When TiKV receives a pushdown request, it checks all the expressions first including the number of the expression arguments.<\/p>\n<p>In TiDB, there is a strict limit for the number of arguments in each built-in function. For the number of arguments, see <code>builtin.go<\/code> in TiDB.<\/p>\n<p>To add argument check:<\/p>\n<ol>\n<li>Go to <code>scalar_function.rs<\/code> in TiKV and find the <code>check_args<\/code> function of <code>ScalarFunc<\/code>.<\/li>\n<li>Add the check for the number of the expression arguments as the implemented signatures do.<\/li>\n<\/ol>\n<div class=\"trackable-btns\"><a href=\"\/download\"><button>Download TiDB<\/button><\/a><br \/>\n<a href=\"https:\/\/share.hsforms.com\/1e2W03wLJQQKPd1d9rCbj_Q2npzm\"><button>Subscribe to Blog<\/button><\/a><\/div>\n<h3>Step 6: Add pushdown support<\/h3>\n<p>TiKV calls the <code>eval<\/code> function to evaluate a row of data and the <code>eval<\/code> function executes the sub-function based on the returned value type. This operation is done in <code>scalar_function.rs<\/code> by <code>dispatch_call<\/code>.<\/p>\n<p>For our example function, <code>MultiplyIntUnsigned<\/code>, the final return value type is <code>Int<\/code>, so <code>INT_CALLS<\/code> can be found in <code>dispatch_call<\/code>. Then take the code of other signatures in <code>INT_CALLS<\/code> as reference and add <code>MultiplyIntUnsigned =&gt; multiply_int_unsigned<\/code>. It indicates that when the function signature <code>MultiplyIntUnsigned<\/code> is being parsed, the implemented function <code>multiply_int_unsigned<\/code> will be called. The pushdown logic of <code>MultiplyIntUnsigned<\/code> is now implemented.<\/p>\n<h3>Step 7: Add at least one test<\/h3>\n<ol>\n<li>Go to <code>builtin_arithmetic.rs<\/code> where the <code>multiply_int_unsigned<\/code> function resides.<\/li>\n<li>Add the unit test for the function signature in the <code>test<\/code> module which is at the end of <code>builtin_arithmetic.rs<\/code>. Make sure that the unit test covers all the code which is added above. You can see the related test code in TiDB for reference.<\/li>\n<\/ol>\n<p>For this example, the test code implemented in TiKV is as follows:<\/p>\n<pre><code class=\"language-rust\">#[test]\nfn test_multiply_int_unsigned() {\n    let cases = vec![\n        (Datum::I64(1), Datum::I64(2), Datum::U64(2)),\n        (\n            Datum::I64(i64::MIN),\n            Datum::I64(1),\n            Datum::U64(i64::MIN as u64),\n        ),\n        (\n            Datum::I64(i64::MAX),\n            Datum::I64(1),\n            Datum::U64(i64::MAX as u64),\n        ),\n        (Datum::U64(u64::MAX), Datum::I64(1), Datum::U64(u64::MAX)),\n    ];\n\n    let mut ctx = EvalContext::default();\n\n    for (left, right, exp) in cases {\n        let lhs = datum_expr(left);\n        let rhs = datum_expr(right);\n        let mut op = Expression::build(\n            &amp;mut ctx,\n            scalar_func_expr(ScalarFuncSig::MultiplyIntUnsigned, &amp;[lhs, rhs]),\n        ).unwrap();\n        op.mut_tp().set_flag(types::UNSIGNED_FLAG as u32);\n        let got = op.eval(&amp;mut ctx, &amp;[]).unwrap();\n        assert_eq!(got, exp);\n    }\n\n    \/\/ test overflow\n    let cases = vec![\n        (Datum::I64(-1), Datum::I64(2)),\n        (Datum::I64(i64::MAX), Datum::I64(i64::MAX)),\n        (Datum::I64(i64::MIN), Datum::I64(i64::MIN)),\n    ];\n\n    for (left, right) in cases {\n        let lhs = datum_expr(left);\n        let rhs = datum_expr(right);\n        let mut op = Expression::build(\n            &amp;mut ctx,\n            scalar_func_expr(ScalarFuncSig::MultiplyIntUnsigned, &amp;[lhs, rhs]),\n        ).unwrap();\n        op.mut_tp().set_flag(types::UNSIGNED_FLAG as u32);\n        let got = op.eval(&amp;mut ctx, &amp;[]).unwrap_err();\n        assert!(check_overflow(got).is_ok());\n    }\n}\n<\/code><\/pre>\n<h3>Step 8: Run the test<\/h3>\n<p>Run <code>make expression<\/code> and ensure that all the test cases can pass the test.<\/p>\n<h3>Step 9: File a PR for TiKV<\/h3>\n<p>After you finish the above steps, you can file a PR for TiKV! After we merge, you are now a honored TiKV contributor! See our <a href=\"https:\/\/github.com\/pingcap\/tidb\/blob\/master\/CONTRIBUTING.md\">Contribution Guide<\/a> for a more comprehensive run-down of becoming a contributor.<\/p>\n<h3>Wrapping Up<\/h3>\n<p>We hope this guide provides an easy entry point to contributing to our Coprocessor, one of TiDB and TiKV&#8217;s core features. If you run into any issues or problems with this guide, please let us know on our <a href=\"https:\/\/twitter.com\/PingCAP\">Twitter<\/a>, <a href=\"https:\/\/www.reddit.com\/r\/TiDB\/\">Reddit<\/a>, <a href=\"https:\/\/stackoverflow.com\/questions\/tagged\/tikv\">Stack Overflow<\/a>, or <a href=\"https:\/\/groups.google.com\/forum\/#!forum\/tidb-user\">Google Group<\/a>. Look forward to seeing your PR, and once it&#8217;s merged, expect a special gift of gratitude from our team!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This guide is intended to show how you can land your first Pull Request (PR) in Rust to contribute to TiKV in less than 30 minutes. But before we do that, here&#8217;s some helpful background.<\/p>","protected":false},"author":8,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"ub_ctt_via":"","footnotes":""},"categories":[18],"tags":[23,22,29],"class_list":["post-121","post","type-post","status-publish","format-standard","hentry","category-community","tag-rust","tag-tikv","tag-tutorial"],"acf":[],"featured_image_src":null,"author_info":{"display_name":"TiDB Team","author_link":"https:\/\/www.pingcap.com\/ko\/blog\/author\/pingcap\/"},"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.9 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Landing Your First Rust Pull Request in TiKV | TiDB<\/title>\n<meta name=\"description\" content=\"Learn about the benefits of TiDB and the TiDB Cloud solutions from PingCAP. Read our latest post &quot;Landing Your First Rust Pull Request in TiKV&quot; here.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.pingcap.com\/ko\/blog\/adding-built-in-functions-to-tikv\/\" \/>\n<meta property=\"og:locale\" content=\"ko_KR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Landing Your First Rust Pull Request in TiKV | TiDB\" \/>\n<meta property=\"og:description\" content=\"Learn about the benefits of TiDB and the TiDB Cloud solutions from PingCAP. Read our latest post &quot;Landing Your First Rust Pull Request in TiKV&quot; here.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.pingcap.com\/ko\/blog\/adding-built-in-functions-to-tikv\/\" \/>\n<meta property=\"og:site_name\" content=\"TiDB\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/facebook.com\/pingcap2015\" \/>\n<meta property=\"article:published_time\" content=\"2018-08-03T00:00:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-03-18T13:31:29+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/static.pingcap.com\/files\/2024\/09\/11005522\/Homepage-Ad.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1440\" \/>\n\t<meta property=\"og:image:height\" content=\"714\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"TiDB Team\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@PingCAP\" \/>\n<meta name=\"twitter:site\" content=\"@PingCAP\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"TiDB Team\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"7\ubd84\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.pingcap.com\/blog\/adding-built-in-functions-to-tikv\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.pingcap.com\/blog\/adding-built-in-functions-to-tikv\/\"},\"author\":{\"name\":\"TiDB Team\",\"@id\":\"https:\/\/www.pingcap.com\/#\/schema\/person\/b17c1fde961eebd318de8729d595df74\"},\"headline\":\"Landing Your First Rust Pull Request in TiKV\",\"datePublished\":\"2018-08-03T00:00:00+00:00\",\"dateModified\":\"2024-03-18T13:31:29+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.pingcap.com\/blog\/adding-built-in-functions-to-tikv\/\"},\"wordCount\":1261,\"publisher\":{\"@id\":\"https:\/\/www.pingcap.com\/#organization\"},\"keywords\":[\"Rust\",\"TiKV\",\"Tutorial\"],\"articleSection\":[\"Community\"],\"inLanguage\":\"ko-KR\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.pingcap.com\/blog\/adding-built-in-functions-to-tikv\/\",\"url\":\"https:\/\/www.pingcap.com\/blog\/adding-built-in-functions-to-tikv\/\",\"name\":\"Landing Your First Rust Pull Request in TiKV | TiDB\",\"isPartOf\":{\"@id\":\"https:\/\/www.pingcap.com\/#website\"},\"datePublished\":\"2018-08-03T00:00:00+00:00\",\"dateModified\":\"2024-03-18T13:31:29+00:00\",\"description\":\"Learn about the benefits of TiDB and the TiDB Cloud solutions from PingCAP. Read our latest post \\\"Landing Your First Rust Pull Request in TiKV\\\" here.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.pingcap.com\/blog\/adding-built-in-functions-to-tikv\/#breadcrumb\"},\"inLanguage\":\"ko-KR\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.pingcap.com\/blog\/adding-built-in-functions-to-tikv\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.pingcap.com\/blog\/adding-built-in-functions-to-tikv\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.pingcap.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Landing Your First Rust Pull Request in TiKV\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.pingcap.com\/#website\",\"url\":\"https:\/\/www.pingcap.com\/\",\"name\":\"TiDB\",\"description\":\"TiDB | SQL at Scale\",\"publisher\":{\"@id\":\"https:\/\/www.pingcap.com\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.pingcap.com\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"ko-KR\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.pingcap.com\/#organization\",\"name\":\"PingCAP\",\"url\":\"https:\/\/www.pingcap.com\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"ko-KR\",\"@id\":\"https:\/\/www.pingcap.com\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/static.pingcap.com\/files\/2021\/11\/pingcap-logo.png\",\"contentUrl\":\"https:\/\/static.pingcap.com\/files\/2021\/11\/pingcap-logo.png\",\"width\":811,\"height\":232,\"caption\":\"PingCAP\"},\"image\":{\"@id\":\"https:\/\/www.pingcap.com\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/facebook.com\/pingcap2015\",\"https:\/\/x.com\/PingCAP\",\"https:\/\/linkedin.com\/company\/pingcap\",\"https:\/\/youtube.com\/channel\/UCuq4puT32DzHKT5rU1IZpIA\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.pingcap.com\/#\/schema\/person\/b17c1fde961eebd318de8729d595df74\",\"name\":\"TiDB Team\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"ko-KR\",\"@id\":\"https:\/\/www.pingcap.com\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/static.pingcap.com\/files\/2022\/10\/17234942\/avatar.jpg\",\"contentUrl\":\"https:\/\/static.pingcap.com\/files\/2022\/10\/17234942\/avatar.jpg\",\"caption\":\"TiDB Team\"},\"url\":\"https:\/\/www.pingcap.com\/ko\/blog\/author\/pingcap\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Landing Your First Rust Pull Request in TiKV | TiDB","description":"Learn about the benefits of TiDB and the TiDB Cloud solutions from PingCAP. Read our latest post \"Landing Your First Rust Pull Request in TiKV\" here.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.pingcap.com\/ko\/blog\/adding-built-in-functions-to-tikv\/","og_locale":"ko_KR","og_type":"article","og_title":"Landing Your First Rust Pull Request in TiKV | TiDB","og_description":"Learn about the benefits of TiDB and the TiDB Cloud solutions from PingCAP. Read our latest post \"Landing Your First Rust Pull Request in TiKV\" here.","og_url":"https:\/\/www.pingcap.com\/ko\/blog\/adding-built-in-functions-to-tikv\/","og_site_name":"TiDB","article_publisher":"https:\/\/facebook.com\/pingcap2015","article_published_time":"2018-08-03T00:00:00+00:00","article_modified_time":"2024-03-18T13:31:29+00:00","og_image":[{"width":1440,"height":714,"url":"https:\/\/static.pingcap.com\/files\/2024\/09\/11005522\/Homepage-Ad.png","type":"image\/png"}],"author":"TiDB Team","twitter_card":"summary_large_image","twitter_creator":"@PingCAP","twitter_site":"@PingCAP","twitter_misc":{"Written by":"TiDB Team","Est. reading time":"7\ubd84"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.pingcap.com\/blog\/adding-built-in-functions-to-tikv\/#article","isPartOf":{"@id":"https:\/\/www.pingcap.com\/blog\/adding-built-in-functions-to-tikv\/"},"author":{"name":"TiDB Team","@id":"https:\/\/www.pingcap.com\/#\/schema\/person\/b17c1fde961eebd318de8729d595df74"},"headline":"Landing Your First Rust Pull Request in TiKV","datePublished":"2018-08-03T00:00:00+00:00","dateModified":"2024-03-18T13:31:29+00:00","mainEntityOfPage":{"@id":"https:\/\/www.pingcap.com\/blog\/adding-built-in-functions-to-tikv\/"},"wordCount":1261,"publisher":{"@id":"https:\/\/www.pingcap.com\/#organization"},"keywords":["Rust","TiKV","Tutorial"],"articleSection":["Community"],"inLanguage":"ko-KR"},{"@type":"WebPage","@id":"https:\/\/www.pingcap.com\/blog\/adding-built-in-functions-to-tikv\/","url":"https:\/\/www.pingcap.com\/blog\/adding-built-in-functions-to-tikv\/","name":"Landing Your First Rust Pull Request in TiKV | TiDB","isPartOf":{"@id":"https:\/\/www.pingcap.com\/#website"},"datePublished":"2018-08-03T00:00:00+00:00","dateModified":"2024-03-18T13:31:29+00:00","description":"Learn about the benefits of TiDB and the TiDB Cloud solutions from PingCAP. Read our latest post \"Landing Your First Rust Pull Request in TiKV\" here.","breadcrumb":{"@id":"https:\/\/www.pingcap.com\/blog\/adding-built-in-functions-to-tikv\/#breadcrumb"},"inLanguage":"ko-KR","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.pingcap.com\/blog\/adding-built-in-functions-to-tikv\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.pingcap.com\/blog\/adding-built-in-functions-to-tikv\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.pingcap.com\/"},{"@type":"ListItem","position":2,"name":"Landing Your First Rust Pull Request in TiKV"}]},{"@type":"WebSite","@id":"https:\/\/www.pingcap.com\/#website","url":"https:\/\/www.pingcap.com\/","name":"\ud2f0DB","description":"TiDB | SQL at Scale","publisher":{"@id":"https:\/\/www.pingcap.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.pingcap.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"ko-KR"},{"@type":"Organization","@id":"https:\/\/www.pingcap.com\/#organization","name":"PingCAP","url":"https:\/\/www.pingcap.com\/","logo":{"@type":"ImageObject","inLanguage":"ko-KR","@id":"https:\/\/www.pingcap.com\/#\/schema\/logo\/image\/","url":"https:\/\/static.pingcap.com\/files\/2021\/11\/pingcap-logo.png","contentUrl":"https:\/\/static.pingcap.com\/files\/2021\/11\/pingcap-logo.png","width":811,"height":232,"caption":"PingCAP"},"image":{"@id":"https:\/\/www.pingcap.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/facebook.com\/pingcap2015","https:\/\/x.com\/PingCAP","https:\/\/linkedin.com\/company\/pingcap","https:\/\/youtube.com\/channel\/UCuq4puT32DzHKT5rU1IZpIA"]},{"@type":"Person","@id":"https:\/\/www.pingcap.com\/#\/schema\/person\/b17c1fde961eebd318de8729d595df74","name":"TiDB Team","image":{"@type":"ImageObject","inLanguage":"ko-KR","@id":"https:\/\/www.pingcap.com\/#\/schema\/person\/image\/","url":"https:\/\/static.pingcap.com\/files\/2022\/10\/17234942\/avatar.jpg","contentUrl":"https:\/\/static.pingcap.com\/files\/2022\/10\/17234942\/avatar.jpg","caption":"TiDB Team"},"url":"https:\/\/www.pingcap.com\/ko\/blog\/author\/pingcap\/"}]}},"grav_blocks":false,"card_markup":"<a class=\"card-resource bg-white\" href=\"https:\/\/www.pingcap.com\/ko\/blog\/adding-built-in-functions-to-tikv\/\"><div class=\"card-resource__content-container\"><div class=\"card-resource__content-head\"><div class=\"card-resource__category\">Community<\/div><\/div><h5 class=\"card-resource__title\">Landing Your First Rust Pull Request in TiKV<\/h5><\/div><\/a>","_links":{"self":[{"href":"https:\/\/www.pingcap.com\/ko\/wp-json\/wp\/v2\/posts\/121","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.pingcap.com\/ko\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.pingcap.com\/ko\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.pingcap.com\/ko\/wp-json\/wp\/v2\/users\/8"}],"replies":[{"embeddable":true,"href":"https:\/\/www.pingcap.com\/ko\/wp-json\/wp\/v2\/comments?post=121"}],"version-history":[{"count":7,"href":"https:\/\/www.pingcap.com\/ko\/wp-json\/wp\/v2\/posts\/121\/revisions"}],"predecessor-version":[{"id":16040,"href":"https:\/\/www.pingcap.com\/ko\/wp-json\/wp\/v2\/posts\/121\/revisions\/16040"}],"wp:attachment":[{"href":"https:\/\/www.pingcap.com\/ko\/wp-json\/wp\/v2\/media?parent=121"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.pingcap.com\/ko\/wp-json\/wp\/v2\/categories?post=121"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.pingcap.com\/ko\/wp-json\/wp\/v2\/tags?post=121"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}