drill apache_Apache Drill:如何创建新功能?
drill apache
Apache Drill允許用戶使用ANSI SQL探索任何類型的數(shù)據(jù)。 這很棒,但是Drill的作用遠(yuǎn)遠(yuǎn)不止于此,它允許您創(chuàng)建自定義函數(shù)來(lái)擴(kuò)展查詢引擎。 這些自定義函數(shù)具有Drill基本操作的所有性能,但是允許執(zhí)行這些性能會(huì)使編寫這些函數(shù)的技巧比您預(yù)期的要復(fù)雜。
在本文中,我將使用一個(gè)非?;镜氖纠鸩秸f(shuō)明如何創(chuàng)建和部署新功能。 請(qǐng)注意,您可以在文檔中找到許多有關(guān)“ 鉆取自定義功能”的信息 。
讓我們創(chuàng)建一個(gè)新函數(shù),使您能夠屏蔽字符串中的某些字符,并使它變得非常簡(jiǎn)單。 新功能將允許用戶從頭開(kāi)始隱藏x個(gè)字符,然后替換為他們選擇的任何字符。 看起來(lái)像:
MASK( 'PASSWORD' , '#' , 4 ) => ####WORD- 您可以在以下Github存儲(chǔ)庫(kù)中找到完整的項(xiàng)目。
如前所述,我們可以想象許多高級(jí)功能,但是我的目標(biāo)是專注于編寫自定義功能的步驟,而不是功能的作用。
先決條件
為此,您將需要:
- Java Developer Kit 7或更高版本
- Apache Drill 1.1或更高版本
- Maven 3.0或更高版本
依存關(guān)系
以下Drill依賴項(xiàng)應(yīng)添加到您的Maven項(xiàng)目中
<dependency><groupId>org.apache.drill.exec</groupId><artifactId>drill-java-exec</artifactId><version>1.1.0</version> </dependency>資源
Mask函數(shù)是DrillSimpleFunc的實(shí)現(xiàn)。
開(kāi)發(fā)人員可以創(chuàng)建兩種類型的自定義函數(shù):
- 簡(jiǎn)單函數(shù):這些函數(shù)將一行作為輸入,并產(chǎn)生一個(gè)值作為輸出
- 聚合函數(shù):接受多行作為輸入并產(chǎn)生一個(gè)值作為輸出
簡(jiǎn)單功能通常稱為UDF,代表用戶定義的功能。 聚合功能稱為UDAF,代表用戶定義的聚合功能。
在此示例中,我們只需要轉(zhuǎn)換每一行上一列的值,因此一個(gè)簡(jiǎn)單的函數(shù)就足夠了。
創(chuàng)建功能
第一步是實(shí)現(xiàn)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() {} }函數(shù)的行為由注釋驅(qū)動(dòng)(第6-10行)*函數(shù)名稱 *函數(shù)范圍 ,在我們的例子中為簡(jiǎn)單*值為NULL時(shí)的操作,在這種情況下,Reverse將僅返回NULL
現(xiàn)在,我們需要使用setup()和eval()方法來(lái)實(shí)現(xiàn)函數(shù)的邏輯。
- setup是不言自明的,在我們這里,我們不需要設(shè)置任何東西。
- eval是該功能的核心。 如您所見(jiàn),此方法沒(méi)有任何參數(shù),并返回void。 那么它是怎樣工作的?
實(shí)際上,該函數(shù)將動(dòng)態(tài)生成(請(qǐng)參閱DrillSimpleFuncHolder ),并且輸入?yún)?shù)和輸出保持器是通過(guò)注釋的保持器定義的。 讓我們來(lái)看看這個(gè)。
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() {}}我們需要定義函數(shù)的參數(shù)。 在這種情況下,我們有3個(gè)參數(shù),每個(gè)參數(shù)都使用@Param批注定義。 此外,我們還必須使用@Output批注定義返回的值。
我們的mask函數(shù)的參數(shù)是:
- 可為空的字符串
- 掩碼字符或字符串
- 從第一個(gè)字符開(kāi)始替換的字符數(shù)
該函數(shù)返回:
- 一串
對(duì)于每個(gè)參數(shù),您都必須使用一個(gè)holder類。 對(duì)于String ,這由VarCharHolder或NullableVarCharHolder 21、24,30行管理,該行提供了一種緩沖區(qū),可以有效地管理較大的對(duì)象。 由于我們正在處理VarChar您還必須注入另一個(gè)緩沖區(qū),該緩沖區(qū)將用于輸出行33-。 請(qǐng)注意,Drill實(shí)際上并不將Java堆用于查詢中正在處理的數(shù)據(jù),而是將這些數(shù)據(jù)保留在堆外,并為我們管理生命周期,而無(wú)需使用Java垃圾收集器。
因?yàn)槲覀冇辛诉m當(dāng)?shù)念?#xff08;輸入/輸出對(duì)象),所以我們差不多完成了,只需要實(shí)現(xiàn)eval()方法本身,并使用這些對(duì)象即可。
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()); }代碼很簡(jiǎn)單:
- 獲取面具本身-第4行
- 獲取值–第5行
- 獲取要替換的字符數(shù)-第7行
- 生成帶有掩碼值的新字符串-第10/11行
- 創(chuàng)建并填充輸出緩沖區(qū)–第14至17行
但是,對(duì)于習(xí)慣于閱讀Java代碼的人來(lái)說(shuō),這段代碼確實(shí)有些奇怪。 之所以會(huì)出現(xiàn)這種奇怪現(xiàn)象,是因?yàn)樵诓樵冎袌?zhí)行的最終代碼實(shí)際上會(huì)即時(shí)生成。 這使Drill可以利用Java的即時(shí)(JIT)編譯器來(lái)達(dá)到最大速度。 要使此工作有效,您必須遵守一些基本規(guī)則:
- 不要使用import,而是使用完全限定的類名 ,這是在第10行使用Strings類完成的。 (來(lái)自Apache Drill中打包的Google Guava API)
- 該ValueHolders類,在我們的例子VarCharHolder和IntHolder應(yīng)該被操縱結(jié)構(gòu)一樣,所以你必須調(diào)用輔助方法,例如getStringFromVarCharHolder和toStringFromUTF8 。 調(diào)用諸如toString類的toString將導(dǎo)致非常嚴(yán)重的問(wèn)題。
現(xiàn)在,我們準(zhǔn)備部署和測(cè)試此新功能。
包
再一次,由于Drill將生成源代碼,因此您必須以在classpath中存在該函數(shù)的類和源代碼的方式準(zhǔn)備軟件包 。 這不同于通常打包Java代碼的方式,但是Drill能夠進(jìn)行必要的代碼生成是必需的。 Drill使用編譯后的代碼訪問(wèn)注釋,并使用源代碼進(jìn)行代碼生成。
一種簡(jiǎn)單的方法是使用maven構(gòu)建項(xiàng)目,尤其是在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>現(xiàn)在,當(dāng)您使用mvn package構(gòu)建時(shí),Maven將生成2個(gè)jar:
- 帶有類和資源的默認(rèn)jar( drill-simple-mask-1.0.jar )
- 第二個(gè)帶有源的jar( drill-simple-mask-1.0-sources.jar )
最后,您必須在項(xiàng)目的resources文件夾中添加drill-module.conf文件,以告訴Drill您的jar包含自定義函數(shù)。 如果您沒(méi)有為功能設(shè)置特定的配置,則可以將此文件保留為空。
一切準(zhǔn)備就緒,您現(xiàn)在可以打包和部署新功能,只需打包并將Jars復(fù)制到Drill 3rd party文件夾中即可; $ DRILL_HOME / jars / 3rdparty,其中$ DRILL_HOME是您的Drill安裝文件夾。
mvn clean packagecp target/*.jar $DRILL_HOME/jars/3rdparty重新開(kāi)始練習(xí)。
跑 !
現(xiàn)在,您應(yīng)該可以在查詢中使用您的函數(shù)了:
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 | ####### | +----------+------------+結(jié)論
在這個(gè)簡(jiǎn)單的項(xiàng)目中,您學(xué)習(xí)了如何編寫,部署和使用自定義的Apache Drill Function。 現(xiàn)在,您可以擴(kuò)展它以創(chuàng)建自己的函數(shù)。
擴(kuò)展Apache Drill(使用自定義功能,存儲(chǔ)插件或格式)時(shí),要記住的一件事是Drill運(yùn)行時(shí)動(dòng)態(tài)生成大量代碼。 這意味著在編寫和部署擴(kuò)展時(shí)可能必須使用非常特定的模式。 使用我們的基本功能,這意味著我們必須:
- 部署類和源
- 使用完全合格的班級(jí)名稱
- 使用值持有者類和輔助方法來(lái)操縱參數(shù)*
翻譯自: https://www.javacodegeeks.com/2015/07/apache-drill-how-to-create-a-new-function.html
drill apache
總結(jié)
以上是生活随笔為你收集整理的drill apache_Apache Drill:如何创建新功能?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 斯柯达正式进入越南市场:首批车型 9 月
- 下一篇: hibernate 别名_Hiberna