[Feature](function) support generating const values from tvf numbers (#28051)
If specified, got a column of constant. otherwise an incremental series like it always be.
mysql> select * from numbers("number" = "5", "const_value" = "-123");
+--------+
| number |
+--------+
| -123 |
| -123 |
| -123 |
| -123 |
| -123 |
+--------+
5 rows in set (0.11 sec)
This commit is contained in:
@ -65,17 +65,23 @@ public class Numbers extends TableValuedFunction {
|
||||
public Statistics computeStats(List<Slot> slots) {
|
||||
Preconditions.checkArgument(slots.size() == 1);
|
||||
try {
|
||||
NumbersTableValuedFunction catalogFunction = (NumbersTableValuedFunction) getCatalogFunction();
|
||||
long rowNum = catalogFunction.getTotalNumbers();
|
||||
NumbersTableValuedFunction numberTvf = (NumbersTableValuedFunction) getCatalogFunction();
|
||||
long rowNum = numberTvf.getTotalNumbers();
|
||||
|
||||
Map<Expression, ColumnStatistic> columnToStatistics = Maps.newHashMap();
|
||||
ColumnStatistic columnStat = new ColumnStatisticBuilder()
|
||||
.setCount(rowNum).setNdv(rowNum).setAvgSizeByte(8).setNumNulls(0).setDataSize(8).setMinValue(0)
|
||||
.setMaxValue(rowNum - 1)
|
||||
.setMinExpr(new IntLiteral(0, Type.BIGINT))
|
||||
.setMaxExpr(new IntLiteral(rowNum - 1, Type.BIGINT))
|
||||
.build();
|
||||
columnToStatistics.put(slots.get(0), columnStat);
|
||||
ColumnStatisticBuilder statBuilder = new ColumnStatisticBuilder()
|
||||
.setCount(rowNum).setAvgSizeByte(8).setNumNulls(0).setDataSize(8);
|
||||
if (numberTvf.getUseConst()) { // a column of const value
|
||||
long value = numberTvf.getConstValue();
|
||||
statBuilder = statBuilder.setNdv(1).setMinValue(value).setMaxValue(value)
|
||||
.setMinExpr(new IntLiteral(value, Type.BIGINT))
|
||||
.setMaxExpr(new IntLiteral(value, Type.BIGINT));
|
||||
} else { // a column of increasing value
|
||||
statBuilder = statBuilder.setNdv(rowNum).setMinValue(0).setMaxValue(rowNum - 1)
|
||||
.setMinExpr(new IntLiteral(0, Type.BIGINT))
|
||||
.setMaxExpr(new IntLiteral(rowNum - 1, Type.BIGINT));
|
||||
}
|
||||
columnToStatistics.put(slots.get(0), statBuilder.build());
|
||||
return new Statistics(rowNum, columnToStatistics);
|
||||
} catch (Exception t) {
|
||||
throw new NereidsException(t.getMessage(), t);
|
||||
|
||||
@ -27,10 +27,8 @@ import org.apache.doris.thrift.TDataGenScanRange;
|
||||
import org.apache.doris.thrift.TScanRange;
|
||||
import org.apache.doris.thrift.TTVFNumbersScanRange;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@ -46,11 +44,15 @@ import java.util.Map;
|
||||
public class NumbersTableValuedFunction extends DataGenTableValuedFunction {
|
||||
public static final String NAME = "numbers";
|
||||
public static final String NUMBER = "number";
|
||||
public static final String CONST_VALUE = "const_value";
|
||||
private static final ImmutableSet<String> PROPERTIES_SET = new ImmutableSet.Builder<String>()
|
||||
.add(NUMBER)
|
||||
.add(CONST_VALUE)
|
||||
.build();
|
||||
// The total numbers will be generated.
|
||||
private long totalNumbers;
|
||||
private boolean useConst = false;
|
||||
private long constValue;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
@ -58,24 +60,27 @@ public class NumbersTableValuedFunction extends DataGenTableValuedFunction {
|
||||
* @throws AnalysisException exception
|
||||
*/
|
||||
public NumbersTableValuedFunction(Map<String, String> params) throws AnalysisException {
|
||||
Map<String, String> validParams = Maps.newHashMap();
|
||||
for (String key : params.keySet()) {
|
||||
if (!PROPERTIES_SET.contains(key.toLowerCase())) {
|
||||
throw new AnalysisException(key + " is invalid property");
|
||||
}
|
||||
validParams.put(key.toLowerCase(), params.get(key));
|
||||
if (!params.containsKey(NUMBER)) {
|
||||
throw new AnalysisException("number not set");
|
||||
}
|
||||
|
||||
String numberStr = validParams.get(NUMBER);
|
||||
if (!Strings.isNullOrEmpty(numberStr)) {
|
||||
try {
|
||||
totalNumbers = Long.parseLong(numberStr);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new AnalysisException("can not parse `number` param to natural number");
|
||||
for (String key : params.keySet()) {
|
||||
if (PROPERTIES_SET.contains(key)) {
|
||||
try {
|
||||
switch (key) {
|
||||
case NUMBER:
|
||||
totalNumbers = Long.parseLong(params.get(key));
|
||||
break;
|
||||
case CONST_VALUE:
|
||||
useConst = true;
|
||||
constValue = Long.parseLong(params.get(key));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
throw new AnalysisException("cannot parse param value " + params.get(key));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new AnalysisException(
|
||||
"can not find `number` param, please specify `number`, like: numbers(\"number\" = \"10\")");
|
||||
}
|
||||
}
|
||||
|
||||
@ -83,6 +88,14 @@ public class NumbersTableValuedFunction extends DataGenTableValuedFunction {
|
||||
return totalNumbers;
|
||||
}
|
||||
|
||||
public boolean getUseConst() {
|
||||
return useConst;
|
||||
}
|
||||
|
||||
public long getConstValue() {
|
||||
return constValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TDataGenFunctionName getDataGenFunctionName() {
|
||||
return TDataGenFunctionName.NUMBERS;
|
||||
@ -116,8 +129,8 @@ public class NumbersTableValuedFunction extends DataGenTableValuedFunction {
|
||||
List<TableValuedFunctionTask> res = Lists.newArrayList();
|
||||
TScanRange scanRange = new TScanRange();
|
||||
TDataGenScanRange dataGenScanRange = new TDataGenScanRange();
|
||||
TTVFNumbersScanRange tvfNumbersScanRange = new TTVFNumbersScanRange();
|
||||
tvfNumbersScanRange.setTotalNumbers(totalNumbers);
|
||||
TTVFNumbersScanRange tvfNumbersScanRange = new TTVFNumbersScanRange().setTotalNumbers(totalNumbers)
|
||||
.setUseConst(useConst).setConstValue(constValue);
|
||||
dataGenScanRange.setNumbersParams(tvfNumbersScanRange);
|
||||
scanRange.setDataGenScanRange(dataGenScanRange);
|
||||
res.add(new TableValuedFunctionTask(backendList.get(0), scanRange));
|
||||
|
||||
Reference in New Issue
Block a user