Skip to content

Commit

Permalink
[TABLE MODEL] Implement CREATE/SHOW/DROP Function and user-defined sc…
Browse files Browse the repository at this point in the history
…alar function
  • Loading branch information
Cpaulyz authored Dec 8, 2024
1 parent 5c84e68 commit 09288da
Show file tree
Hide file tree
Showing 47 changed files with 1,940 additions and 109 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* 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.
*/

package org.apache.iotdb.udf;

import org.apache.iotdb.udf.api.customizer.config.ScalarFunctionConfig;
import org.apache.iotdb.udf.api.customizer.parameter.FunctionParameters;
import org.apache.iotdb.udf.api.exception.UDFException;
import org.apache.iotdb.udf.api.exception.UDFParameterNotValidException;
import org.apache.iotdb.udf.api.relational.ScalarFunction;
import org.apache.iotdb.udf.api.relational.access.Record;
import org.apache.iotdb.udf.api.type.Type;

/** This is an internal example of the ScalarFunction implementation. */
public class ScalarFunctionExample implements ScalarFunction {
/**
* CREATE DATABASE test;
*
* <p>USE test;
*
* <p>CREATE TABLE t1(device_id STRING ID, s1 TEXT MEASUREMENT, s2 INT32 MEASUREMENT);
*
* <p>INSERT INTO t1(time, device_id, s1, s2) VALUES (1, 'd1', 'a', 1), (2, 'd1', null, 2), (3,
* 'd1', 'c', null);
*
* <p>CREATE FUNCTION contain_null AS 'org.apache.iotdb.udf.ScalarFunctionExample';
*
* <p>SHOW FUNCTIONS;
*
* <p>SELECT time, device_id, s1, s2, contain_null(s1, s2) as contain_null, contain_null(s1) as
* s1_isnull, contain_null(s2) as s2_isnull FROM t1;
*/
@Override
public void validate(FunctionParameters parameters) throws UDFException {
if (parameters.getChildExpressionsSize() < 1) {
throw new UDFParameterNotValidException("At least one parameter is required.");
}
}

@Override
public void beforeStart(FunctionParameters parameters, ScalarFunctionConfig configurations) {
configurations.setOutputDataType(Type.BOOLEAN);
}

@Override
public Object evaluate(Record input) throws UDFException {
for (int i = 0; i < input.size(); i++) {
if (input.isNull(i)) {
return true;
}
}
return false;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/*
* 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.
*/

package org.apache.iotdb.db.query.udf.example.relational;

import org.apache.iotdb.udf.api.customizer.config.ScalarFunctionConfig;
import org.apache.iotdb.udf.api.customizer.parameter.FunctionParameters;
import org.apache.iotdb.udf.api.exception.UDFException;
import org.apache.iotdb.udf.api.exception.UDFParameterNotValidException;
import org.apache.iotdb.udf.api.relational.ScalarFunction;
import org.apache.iotdb.udf.api.relational.access.Record;
import org.apache.iotdb.udf.api.type.Type;

import java.util.HashSet;
import java.util.Set;

/** Calculate the sum of all parameters. Only support inputs of INT32,INT64,DOUBLE,FLOAT type. */
public class AllSum implements ScalarFunction {

private Type outputDataType;

@Override
public void validate(FunctionParameters parameters) throws UDFException {
if (parameters.getChildExpressionsSize() < 1) {
throw new UDFParameterNotValidException("At least one parameter is required.");
}
for (int i = 0; i < parameters.getChildExpressionsSize(); i++) {
if (parameters.getDataType(i) != Type.INT32
&& parameters.getDataType(i) != Type.INT64
&& parameters.getDataType(i) != Type.FLOAT
&& parameters.getDataType(i) != Type.DOUBLE) {
throw new UDFParameterNotValidException(
"Only support inputs of INT32,INT64,DOUBLE,FLOAT type.");
}
}
}

@Override
public void beforeStart(FunctionParameters parameters, ScalarFunctionConfig configurations) {
Set<Type> inputTypeSet = new HashSet<>();
for (int i = 0; i < parameters.getChildExpressionsSize(); i++) {
inputTypeSet.add(parameters.getDataType(i));
}
if (inputTypeSet.contains(Type.DOUBLE)) {
outputDataType = Type.DOUBLE;
} else if (inputTypeSet.contains(Type.FLOAT)) {
outputDataType = Type.FLOAT;
} else if (inputTypeSet.contains(Type.INT64)) {
outputDataType = Type.INT64;
} else {
outputDataType = Type.INT32;
}
configurations.setOutputDataType(outputDataType);
}

@Override
public Object evaluate(Record input) {
double res = 0;
for (int i = 0; i < input.size(); i++) {
if (!input.isNull(i)) {
switch (input.getDataType(i)) {
case INT32:
res += input.getInt(i);
break;
case INT64:
res += input.getLong(i);
break;
case FLOAT:
res += input.getFloat(i);
break;
case DOUBLE:
res += input.getDouble(i);
break;
}
}
}
switch (outputDataType) {
case INT32:
return (int) res;
case INT64:
return (long) res;
case FLOAT:
return (float) res;
case DOUBLE:
return res;
default:
throw new RuntimeException("Unexpected output type.");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* 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.
*/

package org.apache.iotdb.db.query.udf.example.relational;

import org.apache.iotdb.udf.api.customizer.config.ScalarFunctionConfig;
import org.apache.iotdb.udf.api.customizer.parameter.FunctionParameters;
import org.apache.iotdb.udf.api.exception.UDFException;
import org.apache.iotdb.udf.api.exception.UDFParameterNotValidException;
import org.apache.iotdb.udf.api.relational.ScalarFunction;
import org.apache.iotdb.udf.api.relational.access.Record;
import org.apache.iotdb.udf.api.type.Type;

public class ContainNull implements ScalarFunction {
@Override
public void validate(FunctionParameters parameters) throws UDFException {
if (parameters.getChildExpressionsSize() < 1) {
throw new UDFParameterNotValidException("At least one parameter is required.");
}
}

@Override
public void beforeStart(FunctionParameters parameters, ScalarFunctionConfig configurations) {
configurations.setOutputDataType(Type.BOOLEAN);
}

@Override
public Object evaluate(Record input) {
for (int i = 0; i < input.size(); i++) {
if (input.isNull(i)) {
return true;
}
}
return false;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* 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.
*/

package org.apache.iotdb.db.query.udf.example.relational;

import org.apache.iotdb.udf.api.customizer.config.ScalarFunctionConfig;
import org.apache.iotdb.udf.api.customizer.parameter.FunctionParameters;
import org.apache.iotdb.udf.api.exception.UDFException;
import org.apache.iotdb.udf.api.exception.UDFParameterNotValidException;
import org.apache.iotdb.udf.api.relational.ScalarFunction;
import org.apache.iotdb.udf.api.relational.access.Record;
import org.apache.iotdb.udf.api.type.Type;

import java.time.LocalDate;

public class DatePlusOne implements ScalarFunction {
@Override
public void validate(FunctionParameters parameters) throws UDFException {
if (parameters.getChildExpressionsSize() != 2) {
throw new UDFParameterNotValidException("Only two parameter is required.");
}
if (parameters.getDataType(0) != Type.DATE) {
throw new UDFParameterNotValidException("The first parameter should be DATE type.");
}
if (parameters.getDataType(1) != Type.INT32 && parameters.getDataType(1) != Type.INT64) {
throw new UDFParameterNotValidException("The second parameter should be INT type.");
}
}

@Override
public void beforeStart(FunctionParameters parameters, ScalarFunctionConfig configurations) {
configurations.setOutputDataType(Type.DATE);
}

@Override
public Object evaluate(Record input) {
LocalDate date = input.getLocalDate(0);
int days = input.getInt(1);
return date.plusDays(days);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

package org.apache.iotdb.confignode.it;

import org.apache.iotdb.common.rpc.thrift.FunctionType;
import org.apache.iotdb.common.rpc.thrift.Model;
import org.apache.iotdb.common.rpc.thrift.TSStatus;
import org.apache.iotdb.common.rpc.thrift.TSeriesPartitionSlot;
Expand Down Expand Up @@ -288,13 +289,15 @@ private List<TCreateFunctionReq> createUDF(SyncConfigNodeIServiceClient client)
TCreateFunctionReq createFunctionReq1 =
new TCreateFunctionReq("test1", "org.apache.iotdb.udf.UDTFExample", true)
.setModel(Model.TREE)
.setFunctionType(FunctionType.NONE)
.setJarName(jarName)
.setJarFile(jarFile)
.setJarMD5(jarMD5);

TCreateFunctionReq createFunctionReq2 =
new TCreateFunctionReq("test2", "org.apache.iotdb.udf.UDTFExample", true)
.setModel(Model.TREE)
.setFunctionType(FunctionType.NONE)
.setJarName(jarName)
.setJarFile(jarFile)
.setJarMD5(jarMD5);
Expand Down
Loading

0 comments on commit 09288da

Please sign in to comment.