Apache Drill:如何创建新功能?

Apache Drill允许用户使用ANSI SQL探索任何类型的数据。 这很棒,但是Drill的作用远远不止于此,它允许您创建自定义函数来扩展查询引擎。 这些自定义功能具有任何Drill基本操作的所有性能,但是允许执行这些性能会使编写这些功能比您期望的要复杂一些。

在本文中,我将使用一个非常基本的示例逐步说明如何创建和部署新功能。 请注意,您可以在文档中找到许多有关“ 钻取自定义功能”的信息 。

让我们创建一个新函数,使您能够屏蔽字符串中的某些字符,并使它变得非常简单。 新功能将允许用户从头开始隐藏x个字符,然后替换为他们选择的任何字符。 看起来像:

MASK( 'PASSWORD' , '#' , 4 ) => ####WORD
  • 您可以在以下Github存储库中找到完整的项目。

如前所述,我们可以想象很多高级功能,但是我的目标是着重于编写自定义功能的步骤,而不是功能的作用。

先决条件

为此,您将需要:

  • Java Developer Kit 7或更高版本
  • Apache Drill 1.1或更高版本
  • Maven 3.0或更高版本

依存关系

以下Drill依赖项应添加到您的Maven项目中

<dependency><groupId>org.apache.drill.exec</groupId><artifactId>drill-java-exec</artifactId><version>1.1.0</version>
</dependency>

资源

Mask函数是DrillSimpleFunc的实现。

开发人员可以创建两种类型的自定义函数:

  • 简单函数:这些函数具有一行作为输入,并产生单个值作为输出
  • 聚合函数:接受多行作为输入并产生一个值作为输出

简单功能通常称为UDF,代表用户定义的功能。 聚合功能称为UDAF,代表用户定义的聚合功能。

在此示例中,我们只需要转换每一行上一列的值,因此一个简单的函数就足够了。

创建功能

第一步是实现DrillSimpleFunc接口。

package org.apache.drill.contrib.function;import org.apache.drill.exec.expr.DrillSimpleFunc;
import org.apache.drill.exec.expr.annotations.FunctionTemplate;@FunctionTemplate(name="mask",scope= FunctionTemplate.FunctionScope.SIMPLE,nulls = FunctionTemplate.NullHandling.NULL_IF_NULL
)
public class SimpleMaskFunc implements DrillSimpleFunc{public void setup() {}public void eval() {}
}

函数的行为由注释驱动(第6-10行)*函数的名称 *函数的范围 ,在我们的情况下为简单*值为NULL时的操作,在这种情况下,Reverse将仅返回NULL

现在,我们需要使用setup()eval()方法来实现函数的逻辑。

  • setup是不言自明的,在我们这里,我们不需要设置任何东西。
  • eval是该功能的核心。 如您所见,此方法没有任何参数,并返回void。 那么它是怎样工作的?

实际上,该函数将动态生成(请参阅DrillSimpleFuncHolder ),并且输入参数和输出保持器是通过注释的保持器定义的。 让我们来看看这个。

import io.netty.buffer.DrillBuf;
import org.apache.drill.exec.expr.DrillSimpleFunc;
import org.apache.drill.exec.expr.annotations.FunctionTemplate;
import org.apache.drill.exec.expr.annotations.Output;
import org.apache.drill.exec.expr.annotations.Param;
import org.apache.drill.exec.expr.holders.IntHolder;
import org.apache.drill.exec.expr.holders.NullableVarCharHolder;
import org.apache.drill.exec.expr.holders.VarCharHolder;import javax.inject.Inject;@FunctionTemplate(name = "mask",scope = FunctionTemplate.FunctionScope.SIMPLE,nulls = FunctionTemplate.NullHandling.NULL_IF_NULL
)
public class SimpleMaskFunc implements DrillSimpleFunc {@ParamNullableVarCharHolder input;@Param(constant = true)VarCharHolder mask;@Param(constant = true)IntHolder toReplace;@OutputVarCharHolder out;@InjectDrillBuf buffer;public void setup() {}public void eval() {}}

我们需要定义函数的参数。 在这种情况下,我们有3个参数,每个参数都使用@Param批注定义。 另外,我们还必须使用@Output注释定义返回的值。

我们的mask函数的参数为​​:

  • 可为空的字符串
  • 掩码字符或字符串
  • 从第一个字符开始替换的字符数

该函数返回:

  • 一串

对于每个参数,您都必须使用一个holder类。 对于String ,这由VarCharHolderNullableVarCharHolder 21、24,30行管理,该行提供了一种缓冲区,可以有效地管理较大的对象。 由于我们正在处理VarChar您还必须注入另一个缓冲区,该缓冲区将用于输出行33-。 请注意,Drill实际上并不将Java堆用于查询中正在处理的数据,而是将这些数据保留在堆外,并为我们管理生命周期,而无需使用Java垃圾收集器。

因为我们有了适当的类(输入/输出对象),所以我们差不多完成了,只需要实现eval()方法本身,并使用这些对象即可。

public void eval() {// get the value and replace withString maskValue = org.apache.drill.exec.expr.fn.impl.StringFunctionHelpers.getStringFromVarCharHolder(mask);String stringValue = org.apache.drill.exec.expr.fn.impl.StringFunctionHelpers.toStringFromUTF8(input.start, input.end, input.buffer);int numberOfCharToReplace = Math.min(toReplace.value, stringValue.length());// build the mask substringString maskSubString = com.google.common.base.Strings.repeat(maskValue, numberOfCharToReplace);String outputValue = (new StringBuilder(maskSubString)).append(stringValue.substring(numberOfCharToReplace)).toString();// put the output value in the out bufferout.buffer = buffer;out.start = 0;out.end = outputValue.getBytes().length;buffer.setBytes(0, outputValue.getBytes());
}

代码很简单:

  • 获取面具本身-第4行
  • 获取值–第5行
  • 获取要替换的字符数–第7行
  • 生成带有掩码值的新字符串-第10/11行
  • 创建并填充输出缓冲区–第14至17行

但是,对于习惯于阅读Java代码的人来说,这段代码确实有些奇怪。 之所以会出现这种奇怪现象,是因为在查询中执行的最终代码实际上会即时生成。 这使Drill可以利用Java的即时(JIT)编译器来达到最大速度。 要使此工作有效,您必须遵守一些基本规则:

  • 不要使用import,而是使用完全限定的类名 ,这是在第10行使用Strings类完成的。 (来自Apache Drill中打包的Google Guava API)
  • ValueHolders类,在我们的例子VarCharHolderIntHolder应该被操纵结构一样,所以你必须调用辅助方法,例如getStringFromVarCharHoldertoStringFromUTF8 。 调用诸如toString类的toString将导致非常严重的问题。

现在,我们准备部署和测试此新功能。

再一次,由于Drill将生成源代码,因此您必须以在classpath中存在函数的类和源代码的方式来准备软件包 。 这不同于通常打包Java代码的方式,但是Drill能够进行必要的代码生成是必需的。 Drill使用编译后的代码访问注释,并使用源代码进行代码生成。

一种简单的方法是使用maven构建项目,尤其是在pom.xml文件中使用如下所示的maven-source-plugin :

<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-source-plugin</artifactId><version>2.4</version><executions><execution><id>attach-sources</id><phase>package</phase><goals><goal>jar-no-fork</goal></goals></execution></executions>
</plugin>

现在,当您使用mvn package构建时,Maven将生成2个jar:

  • 带有类和资源的默认jar( drill-simple-mask-1.0.jar
  • 第二个带有源的jar( drill-simple-mask-1.0-sources.jar

最后,您必须在项目的resources文件夹中添加drill-module.conf文件,以告诉Drill您的jar包含自定义函数。 如果您没有为功能设置特定的配置,则可以将此文件保留为空。

一切准备就绪,您现在可以打包和部署新功能,只需打包并将Jars复制到Drill 3rd party文件夹中即可; $ DRILL_HOME / jars / 3rdparty,其中$ DRILL_HOME是您的Drill安装文件夹。

mvn clean packagecp target/*.jar  $DRILL_HOME/jars/3rdparty

重新开始练习。

跑 !

现在,您应该可以在查询中使用您的函数了:

SELECT MASK(first_name, '*' , 3) FIRST , MASK(last_name, '#', 7) LAST  FROM cp.`employee.json` LIMIT 5;
+----------+------------+
|  FIRST   |    LAST    |
+----------+------------+
| ***ri    | ######     |
| ***rick  | #######    |
| ***hael  | ######     |
| ***a     | #######ez  |
| ***erta  | #######    |
+----------+------------+

结论

在这个简单的项目中,您学习了如何编写,部署和使用自定义的Apache Drill Function。 现在,您可以扩展它以创建自己的函数。

扩展Apache Drill(使用自定义功能,存储插件或格式)时,要记住的一件事是Drill运行时动态生成大量代码。 这意味着在编写和部署扩展时可能必须使用非常特定的模式。 使用我们的基本功能,这意味着我们必须:

  • 部署类和源
  • 使用完全合格的班级名称
  • 使用值持有者类和辅助方法来操纵参数*

翻译自: https://www.javacodegeeks.com/2015/07/apache-drill-how-to-create-a-new-function.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/357403.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Json的访问

JSON&#xff1a;JavaScript 对象表示法&#xff08;JavaScript Object Notation&#xff09; 写法&#xff1a;名称/值对 访问方法&#xff1a;可以通过 data.名称 访问&#xff0c;也可以通过 data[名称] 访问 注意&#xff1a;名称加不加引号都可以&#xff0c;但是加引号安…

让一个文字在背景图片水平居中的方法

最近工作中在做那个可视化大屏&#xff0c;图中用到了大量的装饰图片&#xff0c;下面看一下文字怎么在图片中水平居中。 这个方法比较好用&#xff0c;其他的方法嵌入太多可能不是特别好使&#xff0c;尤其嵌入到多个框架中。 html <!DOCTYPE html> <html><h…

Objective-C中,ARC下的 strong和weak指针原理解释

Objective-C中&#xff0c;ARC下的 strong和weak指针原理解释 提示&#xff1a;本文中所说的"实例变量"即是"成员变量"&#xff0c;"局部变量"即是"本地变量" 一、简介 ARC是自iOS 5之后增加的新特性&#xff0c;完全消除了手动管理内…

elementui去掉表格所有边框

/deep/.el-table {border: 0;th,tr,td{border: 0;background-color: #fff;}&::before {height: 0px;}&::after {width: 0;}.el-table__fixed:before {height: 0;}}

cdi 2.7.5_集成测试CDI 1.0和Spring 3.1中的作用域bean

cdi 2.7.5在这篇博客文章中&#xff0c;我描述了如何在Spring和CDI中使用作用域bean进行集成测试。 一切都用小代码示例进行说明。 使用范围进行集成测试并不是特别容易。 想象一下存在于会话范围内的bean&#xff0c;例如UserCredentials 。 在集成测试中&#xff0c;通常没有…

工作流编写教程

介绍 ONES中使用了flowchart.js作为前端展示&#xff0c;并且扩展了flowchart.js的流程描述语言。flowchart.js 参见&#xff1a; https://github.com/adrai/flowchart.js 描述语言分为三部分&#xff0c;使用\n\n(空一行)作为分割&#xff0c;分别是节点定义、执行流程描述、节…

elementui设置表头与表格(左对齐,背景颜色,字体大小等)

headerStyle控制表头&#xff0c;finalCellStyle控制表格 html <div class"table1"><el-tablesize"mini":data"tableDataLeft"borderstripe:default-sort"defaultSort":max-height"tableMaxH":header-cell-style&…

使用LocalTestServer对HTTP调用进行单元测试

有时候&#xff0c;当您正在对远程服务器进行HTTP调用的单元测试代码时。 您可能正在使用诸如ApachesHttpClient或Spring的RestTemplate之类的库。 当然&#xff0c;您不想依靠远程服务进行单元测试。 除了涉及的开销&#xff08;记住单元测试应该是快速的&#xff09;之外&am…

PHP header函数大全

PHP header函数大全 header(Content-Type: text/html; charsetutf-8); header(Location: http://www.php-note.com/); <?php // fix 404 pages: header(HTTP/1.1 200 OK);// set 404 header: header(HTTP/1.1 404 Not Found);// set Moved Permanently header (good for re…

JS提升(hoisting)

近期在学习js&#xff0c;了解到js的一个名词&#xff0c;就是hoisting&#xff0c;进而了解了下js的解析机制 详情可参考&#xff1a;http://www.runoob.com/js/js-hoisting.html js的解析过程分为两个阶段&#xff1a;编译阶段和执行阶段 编译阶段&#xff1a;即我们常说的…

【Java从入门到天黑|01】SE入门之Java的前生今世

大家好,我是孙叫兽,微信公众号【孙叫兽杂谈】,本期给大家分享一下JavaSE的入门部分之Java的前生今世。 Java : 一个帝国的诞生 C语言帝国的统治 现在是公元1995年, C语言帝国已经统治了我们20多年, 实在是太久了。 1972年, 随着C语言的诞生和Unix的问世, 帝国

前端-html、css

HTML一、html简介超级文本标记语言是标准通用标记语言下的一个应用&#xff0c;也是一种规范&#xff0c;一种标准&#xff0c;它通过标记符号来标记要显示的网页中的各个部分。网页文件本身是一种文本文件&#xff0c;通过在文本文件中添加标记符&#xff0c;可以告诉浏览器如…

在Java EE组件中使用骆驼路线

从现在开始我一直在与Camel合作&#xff0c;我真的很喜欢它的简单性。 在Java EE之上始终使用它一直是一个挑战&#xff0c;而我最近发表的有关如何做到这一点的演讲之一以及Java EE中引导Camel的不同方法实际上建议使用WildFly-Camel Subsystem 。 在正在进行的系列文章中&…

【Java从入门到天黑|02】SE入门之Java基础

大家好,我是孙叫兽,微信公众号【孙叫兽杂谈】,本期给大家分享一下JavaSE的入门部分之Java基础 目录 注释 标识符 数据类型 类型转换 变量,常量 运算符

webpack入门

遇到问题首先到github项目的Issues中&#xff0c;检索一下相关问题&#xff0c;比在百度谷歌上直接搜索非官方解决方案好得多。 1、npm init 生成 package.json 2、npm i -D webpack 生成 # npm i -D 是 npm install --save-dev 的简写&#xff0c;是指安装模块并保存到 packa…

接口自动化 基于python+Testlink+Jenkins实现的接口自动化测试框架

基于pythonTestlinkJenkins实现的接口自动化测试框架 by:授客 QQ&#xff1a;1033553122 博客&#xff1a;http://blog.sina.com.cn/ishouke 欢迎加入软件性能测试交流QQ群&#xff1a;7156436 目录 1、 开发环境... 1 2、 主要功能逻辑介绍... 1 3、 框架…

PC钉钉无法输入汉字的解决办法

问题描述 新公司办公OA使用的钉钉&#xff0c;今天想给设计师发消息呢&#xff0c;发现私活输入不了汉字&#xff0c;早上还行呢&#xff0c; 过程尝试 在百度中可以输入汉字&#xff0c;在钉钉中不行。 解决办法 退出钉钉&#xff0c;重新进入&#xff0c;可以输入汉字了。如果…

this的指向

箭头函数&#xff1a;定义时所在的作用域&#xff08;tip:继承而来 函数作用域 &#xff09; 普通函数&#xff1a;指向调用它的对象 箭头函数体内的 this对象&#xff0c;就是定义时所在的对象&#xff0c;而不是使用时所在的对象 1、箭头函数没有自己的this&#xff0c;ar…

事关每个程序员的职业规划与履历

今天&#xff0c;甚至过去&#xff0c;大多数人都是由自己来设计他们的职业生涯的。 无论你正要启程&#xff0c;还是已经奋斗多年&#xff0c;以下内容都会对您的职业生涯有所助益。 目录 几条重要的职业规划提示。 1. 学习的步伐不停止 2. 学会问、学会听&#xff0c;学会学习…

iOS--viewController

隐藏状态栏 1 -(BOOL)prefersStatusBarHidden{ 2 return YES; 3 } 转载于:https://www.cnblogs.com/chebaodaren/p/5367160.html