| import{_ as l,r as t,o as i,c,a as r,d as s,e as n,b as a,w as d,f as e}from"./app-5cdcb249.js";const u={},k=e('<h1 id="多语言远程-udf-c-c-java" tabindex="-1"><a class="header-anchor" href="#多语言远程-udf-c-c-java" aria-hidden="true">#</a> 多语言远程 UDF(C / C++ / Java / ...)</h1><p>Remote UDF Service 支持通过 RPC 的方式访问用户提供的 UDF Service,以实现用户自定义函数的执行。<br> 相比于 Native 的 UDF 实现,Remote UDF Service 有如下优势:</p><ul><li>跨语言:可以用 Protobuf 支持的各类语言编写 UDF Service。</li><li>安全:UDF 执行失败或崩溃,仅会影响 UDF Service 自身,而不会导致 IoTDB 进程崩溃。</li><li>灵活:UDF Service 中可以调用任意其他服务或程序库类,以满足更多样的业务需求。</li></ul><h2 id="依赖" tabindex="-1"><a class="header-anchor" href="#依赖" aria-hidden="true">#</a> 依赖</h2><h3 id="protobuf-编译安装" tabindex="-1"><a class="header-anchor" href="#protobuf-编译安装" aria-hidden="true">#</a> protobuf 编译安装</h3>',5),h={href:"https://github.com/protocolbuffers/protobuf/releases",target:"_blank",rel:"noopener noreferrer"},m=s("li",null,"确认安装依赖库:automake,autoconf,libtool是否已经安装,未安装的需要安装",-1),b=s("li",null,"下载 protobuf 安装文件,解压",-1),v=s("li",null,"编译 (用于生成编译服务器下可执行程序):",-1),g=e(`<div class="language-bash line-numbers-mode" data-ext="sh"><pre class="language-bash"><code>./autogen.sh |
| ./configure <span class="token parameter variable">--prefix</span><span class="token operator">=</span>/XX/bin/protobuflib/ |
| <span class="token function">make</span> |
| <span class="token function">make</span> <span class="token function">install</span> |
| </code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>如果你使用的是 Java 或 C++等,完成以上步骤就已经可以使用生成的protobuf可执行程序生产protobuf相关文件了。</p><h3 id="protobuf-c-编译安装-c-语言远程-udf-需此步骤" tabindex="-1"><a class="header-anchor" href="#protobuf-c-编译安装-c-语言远程-udf-需此步骤" aria-hidden="true">#</a> protobuf-c 编译安装(C 语言远程 UDF 需此步骤)</h3>`,3),f={href:"https://codechina.csdn.net/mirrors/protobuf-c/protobuf-c/-/releases/v1.4.0?spm=1033.2243.3001.5876",target:"_blank",rel:"noopener noreferrer"},x=s("li",null,"确认安装依赖库:protobuf, 设置之前protobuf编译出的依赖库资源的环境变量:",-1),F=e(`<div class="language-bash line-numbers-mode" data-ext="sh"><pre class="language-bash"><code><span class="token assign-left variable">PKG_CONFIG_PATH</span><span class="token operator">=</span>/XX/bin/protobuflib/ |
| <span class="token builtin class-name">export</span> PKG_CONFIG_PATH |
| </code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div></div></div><ul><li>下载protobuf-c,解压</li><li>编译 (用于生成编译服务器下可执行程序):</li></ul><div class="language-bash line-numbers-mode" data-ext="sh"><pre class="language-bash"><code>./autogen.sh |
| ./configure <span class="token parameter variable">--prefix</span><span class="token operator">=</span>/XX/bin/protobufc/ |
| <span class="token function">make</span> |
| <span class="token function">make</span> <span class="token function">install</span> |
| </code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>protobufc下生成的文件,即为编译生成的依赖库、protobuf-c可执行程序,使用protobuf-c可执行程序可以根据proto文件生成.c和.h文件</p><h2 id="编写-udf-函数" tabindex="-1"><a class="header-anchor" href="#编写-udf-函数" aria-hidden="true">#</a> 编写 UDF 函数</h2><h3 id="拷贝-proto-文件" tabindex="-1"><a class="header-anchor" href="#拷贝-proto-文件" aria-hidden="true">#</a> 拷贝 proto 文件</h3><p>function_service.proto 和 types.proto 拷贝到 Rpc 服务中</p><ul><li>function_service.proto <ul><li>PFunctionCallRequest <ul><li>function_name:函数名称,对应创建函数时指定的symbol</li><li>args:方法传递的参数</li><li>context:查询上下文信息</li></ul></li><li>PFunctionCallResponse <ul><li>result:结果</li><li>status:状态,0代表正常</li></ul></li><li>PCheckFunctionRequest <ul><li>function:函数相关信息</li><li>match_type:匹配类型</li></ul></li><li>PCheckFunctionResponse <ul><li>status:状态,0代表正常</li></ul></li></ul></li></ul><h3 id="生成接口" tabindex="-1"><a class="header-anchor" href="#生成接口" aria-hidden="true">#</a> 生成接口</h3><p>通过 protoc 生成代码,具体参数通过 protoc -h 查看</p><h3 id="实现接口" tabindex="-1"><a class="header-anchor" href="#实现接口" aria-hidden="true">#</a> 实现接口</h3><p>共需要实现以下三个方法</p><ul><li>fnCall:用于编写计算逻辑</li><li>checkFn:用于创建 UDF 时校验,校验函数名/参数/返回值等是否合法</li><li>handShake:用于接口探活</li></ul><h2 id="创建-udf" tabindex="-1"><a class="header-anchor" href="#创建-udf" aria-hidden="true">#</a> 创建 UDF</h2><div class="language-sql line-numbers-mode" data-ext="sql"><pre class="language-sql"><code><span class="token keyword">CREATE</span> <span class="token keyword">FUNCTION</span> <span class="token operator"><</span>UDF<span class="token operator">-</span>NAME<span class="token operator">></span> <span class="token keyword">AS</span> |
| SYMBOL <span class="token operator">=</span> <span class="token operator"><</span>SYMBOL<span class="token operator">></span><span class="token punctuation">,</span> |
| OBJECT_FILE <span class="token operator">=</span> <span class="token operator"><</span>OBJECT_FILE<span class="token operator">></span><span class="token punctuation">,</span> |
| <span class="token keyword">LANGUAGE</span> PROTOBUF |
| </code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>说明:</p><ol><li><code>symbol</code>表示的是 rpc 调用传递的方法名,这个参数是必须设定的。</li><li><code>object_file</code>表示的 rpc 服务地址,目前支持单个地址和 brpc 兼容格式的集群地址。</li></ol><p>示例:</p><div class="language-sql line-numbers-mode" data-ext="sql"><pre class="language-sql"><code><span class="token keyword">CREATE</span> <span class="token keyword">FUNCTION</span> rpc_udf1 <span class="token keyword">AS</span> |
| SYMBOL <span class="token operator">=</span> <span class="token string">"fnCall"</span><span class="token punctuation">,</span> |
| OBJECT_FILE <span class="token operator">=</span> <span class="token string">"127.0.0.1:9090"</span><span class="token punctuation">,</span> |
| <span class="token keyword">LANGUAGE</span> PROTOBUF<span class="token punctuation">;</span> |
| </code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="udf-卸载" tabindex="-1"><a class="header-anchor" href="#udf-卸载" aria-hidden="true">#</a> UDF 卸载</h2><p>卸载 UDF 的 SQL 语法如下:</p><div class="language-sql line-numbers-mode" data-ext="sql"><pre class="language-sql"><code><span class="token keyword">DROP</span> <span class="token keyword">FUNCTION</span> <span class="token operator"><</span>UDF<span class="token operator">-</span>NAME<span class="token operator">></span> |
| </code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><p>例如:</p><div class="language-sql line-numbers-mode" data-ext="sql"><pre class="language-sql"><code><span class="token keyword">DROP</span> <span class="token keyword">FUNCTION</span> rpc_udf1 |
| </code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><h2 id="udf-查询" tabindex="-1"><a class="header-anchor" href="#udf-查询" aria-hidden="true">#</a> UDF 查询</h2><p>UDF 的使用方法与普通内建函数的类似。</p><h3 id="支持的基础-sql-语法" tabindex="-1"><a class="header-anchor" href="#支持的基础-sql-语法" aria-hidden="true">#</a> 支持的基础 SQL 语法</h3><ul><li><code>SLIMIT</code> / <code>SOFFSET</code></li><li><code>LIMIT</code> / <code>OFFSET</code></li><li>支持值过滤</li><li>支持时间过滤</li></ul><h3 id="带-查询" tabindex="-1"><a class="header-anchor" href="#带-查询" aria-hidden="true">#</a> 带 * 查询</h3><p>假定现在有时间序列 <code>root.sg.d1.s1</code>和 <code>root.sg.d1.s2</code>。</p><ul><li><strong>执行<code>SELECT example(*) from root.sg.d1</code></strong></li></ul><p>那么结果集中将包括<code>example(root.sg.d1.s1)</code>和<code>example(root.sg.d1.s2)</code>的结果。</p><ul><li><strong>执行<code>SELECT example(s1, *) from root.sg.d1</code></strong></li></ul><p>那么结果集中将包括<code>example(root.sg.d1.s1, root.sg.d1.s1)</code>和<code>example(root.sg.d1.s1, root.sg.d1.s2)</code>的结果。</p><ul><li><strong>执行<code>SELECT example(*, *) from root.sg.d1</code></strong></li></ul><p>那么结果集中将包括<code>example(root.sg.d1.s1, root.sg.d1.s1)</code>,<code>example(root.sg.d1.s2, root.sg.d1.s1)</code>,<code>example(root.sg.d1.s1, root.sg.d1.s2)</code> 和 <code>example(root.sg.d1.s2, root.sg.d1.s2)</code>的结果。</p><h3 id="带自定义输入参数的查询" tabindex="-1"><a class="header-anchor" href="#带自定义输入参数的查询" aria-hidden="true">#</a> 带自定义输入参数的查询</h3><p>您可以在进行 UDF 查询的时候,向 UDF 传入任意数量的键值对参数。键值对中的键和值都需要被单引号或者双引号引起来。注意,键值对参数只能在所有时间序列后传入。下面是一组例子:</p><div class="language-sql line-numbers-mode" data-ext="sql"><pre class="language-sql"><code><span class="token keyword">SELECT</span> example<span class="token punctuation">(</span>s1<span class="token punctuation">,</span> <span class="token string">'key1'</span><span class="token operator">=</span><span class="token string">'value1'</span><span class="token punctuation">,</span> <span class="token string">'key2'</span><span class="token operator">=</span><span class="token string">'value2'</span><span class="token punctuation">)</span><span class="token punctuation">,</span> example<span class="token punctuation">(</span><span class="token operator">*</span><span class="token punctuation">,</span> <span class="token string">'key3'</span><span class="token operator">=</span><span class="token string">'value3'</span><span class="token punctuation">)</span> <span class="token keyword">FROM</span> root<span class="token punctuation">.</span>sg<span class="token punctuation">.</span>d1<span class="token punctuation">;</span> |
| <span class="token keyword">SELECT</span> example<span class="token punctuation">(</span>s1<span class="token punctuation">,</span> s2<span class="token punctuation">,</span> <span class="token string">'key1'</span><span class="token operator">=</span><span class="token string">'value1'</span><span class="token punctuation">,</span> <span class="token string">'key2'</span><span class="token operator">=</span><span class="token string">'value2'</span><span class="token punctuation">)</span> <span class="token keyword">FROM</span> root<span class="token punctuation">.</span>sg<span class="token punctuation">.</span>d1<span class="token punctuation">;</span> |
| </code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="与其他查询的嵌套查询" tabindex="-1"><a class="header-anchor" href="#与其他查询的嵌套查询" aria-hidden="true">#</a> 与其他查询的嵌套查询</h3><div class="language-sql line-numbers-mode" data-ext="sql"><pre class="language-sql"><code><span class="token keyword">SELECT</span> s1<span class="token punctuation">,</span> s2<span class="token punctuation">,</span> example<span class="token punctuation">(</span>s1<span class="token punctuation">,</span> s2<span class="token punctuation">)</span> <span class="token keyword">FROM</span> root<span class="token punctuation">.</span>sg<span class="token punctuation">.</span>d1<span class="token punctuation">;</span> |
| <span class="token keyword">SELECT</span> <span class="token operator">*</span><span class="token punctuation">,</span> example<span class="token punctuation">(</span><span class="token operator">*</span><span class="token punctuation">)</span> <span class="token keyword">FROM</span> root<span class="token punctuation">.</span>sg<span class="token punctuation">.</span>d1 <span class="token keyword">DISABLE</span> ALIGN<span class="token punctuation">;</span> |
| <span class="token keyword">SELECT</span> s1 <span class="token operator">*</span> example<span class="token punctuation">(</span><span class="token operator">*</span> <span class="token operator">/</span> s1 <span class="token operator">+</span> s2<span class="token punctuation">)</span> <span class="token keyword">FROM</span> root<span class="token punctuation">.</span>sg<span class="token punctuation">.</span>d1<span class="token punctuation">;</span> |
| <span class="token keyword">SELECT</span> s1<span class="token punctuation">,</span> s2<span class="token punctuation">,</span> s1 <span class="token operator">+</span> example<span class="token punctuation">(</span>s1<span class="token punctuation">,</span> s2<span class="token punctuation">)</span><span class="token punctuation">,</span> s1 <span class="token operator">-</span> example<span class="token punctuation">(</span>s1 <span class="token operator">+</span> example<span class="token punctuation">(</span>s1<span class="token punctuation">,</span> s2<span class="token punctuation">)</span> <span class="token operator">/</span> s2<span class="token punctuation">)</span> <span class="token keyword">FROM</span> root<span class="token punctuation">.</span>sg<span class="token punctuation">.</span>d1<span class="token punctuation">;</span> |
| </code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="查看所有注册的-udf" tabindex="-1"><a class="header-anchor" href="#查看所有注册的-udf" aria-hidden="true">#</a> 查看所有注册的 UDF</h2><div class="language-sql line-numbers-mode" data-ext="sql"><pre class="language-sql"><code><span class="token keyword">SHOW</span> FUNCTIONS |
| </code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><h2 id="用户权限管理" tabindex="-1"><a class="header-anchor" href="#用户权限管理" aria-hidden="true">#</a> 用户权限管理</h2><p>用户在使用 UDF 时会涉及到 3 种权限:</p><ul><li><code>CREATE_FUNCTION</code>:具备该权限的用户才被允许执行 UDF 注册操作</li><li><code>DROP_FUNCTION</code>:具备该权限的用户才被允许执行 UDF 卸载操作</li><li><code>READ_TIMESERIES</code>:具备该权限的用户才被允许使用 UDF 进行查询</li></ul>`,46);function _(E,S){const o=t("ExternalLinkIcon"),p=t("RouterLink");return i(),c("div",null,[r(` |
| |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, |
| software distributed under the License is distributed on an |
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| KIND, either express or implied. See the License for the |
| specific language governing permissions and limitations |
| under the License. |
| |
| `),k,s("ul",null,[s("li",null,[n("下载地址 "),s("a",h,[n("https://github.com/protocolbuffers/protobuf/releases"),a(o)])]),m,b,v]),g,s("ul",null,[s("li",null,[n("下载地址: "),s("a",f,[n("https://codechina.csdn.net/mirrors/protobuf-c/protobuf-c/-/releases/v1.4.0?spm=1033.2243.3001.5876"),a(o)])]),x]),F,s("p",null,[n("更多用户权限相关的内容,请参考 "),a(p,{to:"/zh/UserGuide/V1.2.x/stage/Administration-Management/Administration.html"},{default:d(()=>[n("权限管理语句")]),_:1}),n("。")])])}const y=l(u,[["render",_],["__file","User-Defined-Function-C_timecho.html.vue"]]);export{y as default}; |