drill apache_Apache Drill:如何创建新功能?

drill apache

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

drill apache

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

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

相关文章

python往npy写入数据_Python 存取npy格式数据实例

数据处理的时候主要通过两个函数(1):np.save(“test.npy”&#xff0c;数据结构) ----存数据(2):data np.load(test.npy") ----取数据给2个例子如下(存列表)1、z [[[1, 2, 3], [w]], [[1, 2, 3], [w]]]np.save(test.npy, z)x np.load(test.npy) x:->array([[list([1,…

Linux上C语言程序编译过程详解

点击蓝字关注我们因公众号更改推送规则&#xff0c;请点“在看”并加“星标”第一时间获取精彩技术分享来源于网络&#xff0c;侵删本文将介绍如何将高层的C/C语言编写的程序转换成为处理器能够执行的二进制代码的过程&#xff0c;包括四个步骤&#xff1a;预处理&#xff08;P…

hibernate 别名_Hibernate:在sqlRestriction上使用联接表别名

hibernate 别名如果在复杂查询的情况下使用Hibernate模式&#xff0c;则需要使用sql。 因此&#xff0c;sqlRestrictions可以解决。 但是&#xff0c;对联接表别名使用sql限制有点棘手。 将有三个表&#xff1a; 公司表。 员工表。 每个员工都属于一个公司&#xff0c;因此…

C语言,动图展示十大经典排序算法

点击蓝字关注我们因公众号更改推送规则&#xff0c;请点“在看”并加“星标”第一时间获取精彩技术分享来源于网络&#xff0c;侵删以前也零零碎碎发过一些排序算法&#xff0c;但排版都不太好&#xff0c;又重新整理一次&#xff0c;排序算法是数据结构的重要部分&#xff0c;…

python求偏度系数_用 Python 讲解偏度和峰度

之前笔者在做一个金融数据项目时,有朋友问我,衡量股票收益率有没有什么好的方法。这个问题让笔者也思索了好久,其实股票的收益率如果我们从本质来看不就是数据吗,无非就是收益率我们就想让其越高越好,也就是让这个数据增加得越多越好。而衡量数据我们经常用到的方法有均值…

java ee各类组件_在Java EE组件中使用骆驼路线

java ee各类组件从现在开始我一直在与Camel合作&#xff0c;我真的很喜欢它的简单性。 在Java EE之上使用它一直是一个挑战&#xff0c;我最近发表了一篇关于如何做到这一点的演讲&#xff0c;而在Java EE中引导Camel的不同方法实际上建议使用WildFly-Camel Subsystem 。 在正在…

5gnr帧结构特点有哪些_真空离子束刻蚀设备的结构特点有哪些

离子束刻蚀设备有立式、卧式两种结构。通常情况下&#xff0c;该设备以卧式的结构居多&#xff0c;因为采用卧式结构的话&#xff0c;离子源发出的离子束为水平喷射方向&#xff0c;大部分的刻蚀溅射物将落在真空室的底部&#xff0c;可在一定程度上将溅射材料的重新沉积减少。…

老了就不能编程?大龄程序员在线“辟谣”:15 年后,我变得更好了

点击蓝字关注我们因公众号更改推送规则&#xff0c;请点“在看”并加“星标”第一时间获取精彩技术分享来源于网络&#xff0c;侵删几年前&#xff0c;Quora 上的一个提问在程序员圈内掀起热议&#xff1a;“随着年龄的增长&#xff0c;人们会对编程失去兴趣吗&#xff1f;预计…

wildfly管理控制台_WildFly管理控制台已更新–请求反馈

wildfly管理控制台红帽JBoss企业应用程序平台&#xff08;EAP&#xff09;和WildFly具有共生关系 。 简而言之&#xff0c;红帽JBoss企业应用程序平台&#xff08;JBoss EAP&#xff09;保留了WildFly社区项目&#xff08;以前称为JBoss Application Server&#xff09;的所有创…

linux 的ip 设置lo_Linux服务器设置静态IP的方法

这里以CentOS 7系列为例设置静态IP&#xff0c;原来RedHat系列的Linux发行版可以通过setup工具方便的设置静态IP&#xff0c;但是在版本7之后setup工具的功能就逐渐减弱了&#xff0c;所以这时候采用修改配置文件的方式来设置静态IP&#xff0c;方法如下&#xff1a;首先注意&a…

性能测试中脚本怎么写_脚本在流程中的性能影响

性能测试中脚本怎么写我们经常看到人们出于各种目的而使用脚本&#xff08;例如&#xff0c;在服务任务&#xff0c;执行侦听器等中&#xff09;。 使用脚本和Java逻辑通常很有意义&#xff1a; 它不需要打包到jar中并放在classpath上 它使流程定义更易于理解&#xff1a;无需…

vscode 调试参数_如何通过vscode运行调试javascript代码

初次正式要写 javascript 相关的代码,想要用 vscode 直接编译 js 代码,但是发现没有那么简单,需要配置好 launch.json 文件,现已经在vscode上编译过去并且可以调试 javascript 代码,总结了两种方法,分享给大家.方法一: 在 js 后缀文件中写 javascript 代码.1. 环境配置:(1). 需…

超炫酷的C语言技巧

点击蓝字关注我们因公众号更改推送规则&#xff0c;请点“在看”并加“星标”第一时间获取精彩技术分享来源于网络&#xff0c;侵删C语言常常让人觉得它所能表达的东西非常有限。它不具有类似第一级函数和模式匹配这样的高级功能。但是C非常简单&#xff0c;并且仍然有一些非常…

java8默认垃圾收集器_Java 8中最快的垃圾收集器是什么?

java8默认垃圾收集器OpenJDK 8具有几种垃圾收集器算法&#xff0c;例如Parallel GC &#xff0c; CMS和G1 。 哪一个最快&#xff1f; 如果默认GC从Java 8中的并行GC更改为Java 9中的G1&#xff08;当前建议&#xff09;&#xff0c;将会发生什么&#xff1f; 让我们对其进行基…

u盘启动 联想一体机_联想Y430pAT-ISE(H)U盘安装Win7系统教程

最近听到有人在问联想Y430pAT-ISE(H)笔记本安装WIN 7系统的方法&#xff0c;联想Y430pAT-ISE(H)笔记本从发行到现在也快5年了&#xff0c;不过有人在问该电脑安装系统就说明有人还在使用&#xff0c;关于联想Y430pAT-ISE(H)安装Win 7系统的方法有很多&#xff0c;不过大多过时了…

收藏|C语言常用的一些转换工具函数!

点击蓝字关注我们因公众号更改推送规则&#xff0c;请点“在看”并加“星标”第一时间获取精彩技术分享来源于网络&#xff0c;侵删1、字符串转十六进制代码实现&#xff1a;void StrToHex(char *pbDest, char *pbSrc, int nLen) {char h1,h2;char s1,s2;int i;for (i0; i<n…

jit编译_意外分配– JIT编译抖动

jit编译在研究ByteWatcher时 &#xff08;请参阅我的上一篇 文章 &#xff09;&#xff0c;我遇到了一些非常奇怪的事情。 这是实际的代码段&#xff0c;用于找出特定线程上的分配量&#xff1a; return (long) mBeanServer.invoke(name,GET_THREAD_ALLOCATED_BYTES,PARAMS,S…

网页设计图片向上浮动_利用js实现图片在浏览器中飘动(浮动窗口自由移动)效果...

首先&#xff0c;设置一个将要飘动的窗口&#xff0c;html代码如下:利用js控制span标签在浏览器内移动var xPos 0;var yPos 0; var step 1;var delay 10;var height 0;var Hoffset 0;var Woffset 0; var yon 0;var xon 0; var xon 0; var interval;var img document…

apache camel_学习Apache Camel –实时索引推文

apache camel在大多数软件开发项目中&#xff0c;有一点需要使应用程序开始与其他应用程序或第三方组件通信。 无论是发送电子邮件通知&#xff0c;调用外部api&#xff0c;写入文件还是将数据从一个地方迁移到另一个地方&#xff0c;您都可以推出自己的解决方案或利用现有框架…

让你不再害怕指针——C指针详解(经典,非常详细)

点击蓝字关注我们因公众号更改推送规则&#xff0c;请点“在看”并加“星标”第一时间获取精彩技术分享来源于网络&#xff0c;侵删前言:复杂类型说明要了解指针,多多少少会出现一些比较复杂的类型,所以我先介绍一下如何完全理解一个复杂类型,要理解复杂类型其实很简单,一个类型…