Skip to content

Commit

Permalink
[CALCITE-6314] Add RANDOM function (enabled in Postgres library)
Browse files Browse the repository at this point in the history
  • Loading branch information
jduo authored and tanclary committed Mar 14, 2024
1 parent f0dc2b0 commit 9c0d690
Show file tree
Hide file tree
Showing 7 changed files with 65 additions and 68 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@
import static org.apache.calcite.sql.fun.SqlLibraryOperators.PARSE_TIMESTAMP;
import static org.apache.calcite.sql.fun.SqlLibraryOperators.PARSE_URL;
import static org.apache.calcite.sql.fun.SqlLibraryOperators.POW;
import static org.apache.calcite.sql.fun.SqlLibraryOperators.RANDOM;
import static org.apache.calcite.sql.fun.SqlLibraryOperators.REGEXP;
import static org.apache.calcite.sql.fun.SqlLibraryOperators.REGEXP_CONTAINS;
import static org.apache.calcite.sql.fun.SqlLibraryOperators.REGEXP_EXTRACT;
Expand Down Expand Up @@ -652,6 +653,7 @@ Builder populate() {
BuiltInMethod.RAND_SEED.method);
defineReflective(RAND_INTEGER, BuiltInMethod.RAND_INTEGER.method,
BuiltInMethod.RAND_INTEGER_SEED.method);
defineReflective(RANDOM, BuiltInMethod.RAND.method);

defineMethod(ACOS, BuiltInMethod.ACOS.method, NullPolicy.STRICT);
defineMethod(ACOSH, BuiltInMethod.ACOSH.method, NullPolicy.STRICT);
Expand Down
51 changes: 36 additions & 15 deletions core/src/main/java/org/apache/calcite/sql/SqlBasicFunction.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ public class SqlBasicFunction extends SqlFunction {
private final SqlOperandHandler operandHandler;
private final int callValidator;
private final Function<SqlOperatorBinding, SqlMonotonicity> monotonicityInference;
private final boolean dynamic;

//~ Constructors -----------------------------------------------------------

Expand All @@ -73,7 +74,8 @@ private SqlBasicFunction(String name, SqlKind kind, SqlSyntax syntax,
SqlOperandTypeChecker operandTypeChecker,
Integer callValidator,
SqlFunctionCategory category,
Function<SqlOperatorBinding, SqlMonotonicity> monotonicityInference) {
Function<SqlOperatorBinding, SqlMonotonicity> monotonicityInference,
boolean dynamic) {
super(name, kind,
requireNonNull(returnTypeInference, "returnTypeInference"),
operandTypeInference,
Expand All @@ -84,6 +86,7 @@ private SqlBasicFunction(String name, SqlKind kind, SqlSyntax syntax,
this.callValidator = requireNonNull(callValidator, "callValidator");
this.monotonicityInference =
requireNonNull(monotonicityInference, "monotonicityInference");
this.dynamic = dynamic;
}

/** Creates a {@code SqlBasicFunction} whose name is the same as its kind
Expand All @@ -94,7 +97,7 @@ public static SqlBasicFunction create(SqlKind kind,
return new SqlBasicFunction(kind.name(), kind,
SqlSyntax.FUNCTION, true, returnTypeInference, null,
OperandHandlers.DEFAULT, operandTypeChecker, 0,
SqlFunctionCategory.SYSTEM, call -> SqlMonotonicity.NOT_MONOTONIC);
SqlFunctionCategory.SYSTEM, call -> SqlMonotonicity.NOT_MONOTONIC, false);
}

/** Creates a {@code SqlBasicFunction}
Expand All @@ -106,7 +109,7 @@ public static SqlBasicFunction create(String name,
return new SqlBasicFunction(name, SqlKind.OTHER_FUNCTION,
SqlSyntax.FUNCTION, true, returnTypeInference, null,
OperandHandlers.DEFAULT, operandTypeChecker, 0,
SqlFunctionCategory.NUMERIC, call -> SqlMonotonicity.NOT_MONOTONIC);
SqlFunctionCategory.NUMERIC, call -> SqlMonotonicity.NOT_MONOTONIC, false);
}

/** Creates a {@code SqlBasicFunction}
Expand All @@ -117,7 +120,7 @@ public static SqlBasicFunction create(String name,
return new SqlBasicFunction(name, SqlKind.OTHER_FUNCTION,
SqlSyntax.FUNCTION, true, returnTypeInference, null,
OperandHandlers.DEFAULT, operandTypeChecker, 0,
category, call -> SqlMonotonicity.NOT_MONOTONIC);
category, call -> SqlMonotonicity.NOT_MONOTONIC, false);
}

//~ Methods ----------------------------------------------------------------
Expand Down Expand Up @@ -151,35 +154,39 @@ public static SqlBasicFunction create(String name,
super.validateCall(call, validator, scope, operandScope);
}

@Override public boolean isDynamicFunction() {
return dynamic;
}

/** Returns a copy of this function with a given name. */
public SqlBasicFunction withName(String name) {
return new SqlBasicFunction(name, kind, syntax, deterministic,
getReturnTypeInference(), getOperandTypeInference(), operandHandler,
getOperandTypeChecker(), callValidator,
getFunctionType(), monotonicityInference);
getFunctionType(), monotonicityInference, dynamic);
}

/** Returns a copy of this function with a given kind. */
public SqlBasicFunction withKind(SqlKind kind) {
return new SqlBasicFunction(getName(), kind, syntax, deterministic,
getReturnTypeInference(), getOperandTypeInference(), operandHandler,
getOperandTypeChecker(), callValidator,
getFunctionType(), monotonicityInference);
getFunctionType(), monotonicityInference, dynamic);
}

/** Returns a copy of this function with a given category. */
public SqlBasicFunction withFunctionType(SqlFunctionCategory category) {
return new SqlBasicFunction(getName(), kind, syntax, deterministic,
getReturnTypeInference(), getOperandTypeInference(), operandHandler,
getOperandTypeChecker(), callValidator, category, monotonicityInference);
getOperandTypeChecker(), callValidator, category, monotonicityInference, dynamic);
}

/** Returns a copy of this function with a given syntax. */
public SqlBasicFunction withSyntax(SqlSyntax syntax) {
return new SqlBasicFunction(getName(), kind, syntax, deterministic,
getReturnTypeInference(), getOperandTypeInference(), operandHandler,
getOperandTypeChecker(), callValidator,
getFunctionType(), monotonicityInference);
getFunctionType(), monotonicityInference, dynamic);
}

/** Returns a copy of this function with a given strategy for inferring
Expand All @@ -189,7 +196,7 @@ public SqlBasicFunction withReturnTypeInference(
return new SqlBasicFunction(getName(), kind, syntax, deterministic,
returnTypeInference, getOperandTypeInference(), operandHandler,
getOperandTypeChecker(), callValidator,
getFunctionType(), monotonicityInference);
getFunctionType(), monotonicityInference, dynamic);
}

/** Returns a copy of this function with a given strategy for inferring
Expand All @@ -199,7 +206,7 @@ public SqlBasicFunction withOperandTypeInference(
return new SqlBasicFunction(getName(), kind, syntax, deterministic,
getReturnTypeInference(), operandTypeInference, operandHandler,
getOperandTypeChecker(), callValidator,
getFunctionType(), monotonicityInference);
getFunctionType(), monotonicityInference, dynamic);
}

/** Returns a copy of this function with a given strategy for handling
Expand All @@ -208,14 +215,14 @@ public SqlBasicFunction withOperandHandler(SqlOperandHandler operandHandler) {
return new SqlBasicFunction(getName(), kind, syntax, deterministic,
getReturnTypeInference(), getOperandTypeInference(), operandHandler,
getOperandTypeChecker(), callValidator,
getFunctionType(), monotonicityInference);
getFunctionType(), monotonicityInference, dynamic);
}
/** Returns a copy of this function with a given determinism. */
public SqlBasicFunction withDeterministic(boolean deterministic) {
return new SqlBasicFunction(getName(), kind, syntax, deterministic,
getReturnTypeInference(), getOperandTypeInference(), operandHandler,
getOperandTypeChecker(), callValidator,
getFunctionType(), monotonicityInference);
getFunctionType(), monotonicityInference, dynamic);
}

/** Returns a copy of this function with a given strategy for inferring
Expand All @@ -225,13 +232,27 @@ public SqlBasicFunction withMonotonicityInference(
return new SqlBasicFunction(getName(), kind, syntax, deterministic,
getReturnTypeInference(), getOperandTypeInference(), operandHandler,
getOperandTypeChecker(), callValidator,
getFunctionType(), monotonicityInference);
getFunctionType(), monotonicityInference, dynamic);
}

public SqlBasicFunction withValidation(int callValidator) {
return new SqlBasicFunction(getName(), kind, syntax, deterministic,
getReturnTypeInference(), getOperandTypeInference(), operandHandler,
getOperandTypeChecker(), callValidator,
getFunctionType(), monotonicityInference, dynamic);
}

public SqlFunction withValidation(int callValidator) {
public SqlBasicFunction withDynamic(boolean dynamic) {
return new SqlBasicFunction(getName(), kind, syntax, deterministic,
getReturnTypeInference(), getOperandTypeInference(), operandHandler,
getOperandTypeChecker(), callValidator,
getFunctionType(), monotonicityInference);
getFunctionType(), monotonicityInference, dynamic);
}

public SqlBasicFunction withOperandTypeChecker(SqlOperandTypeChecker operandTypeChecker) {
return new SqlBasicFunction(getName(), kind, syntax, deterministic,
getReturnTypeInference(), getOperandTypeInference(), operandHandler,
operandTypeChecker, callValidator,
getFunctionType(), monotonicityInference, dynamic);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2311,4 +2311,10 @@ private static RelDataType deriveTypeMapFromEntries(SqlOperatorBinding opBinding
@LibraryOperator(libraries = {SPARK})
public static final SqlFunction GETBIT =
BIT_GET.withName("GETBIT");

/** The RANDOM() function. Equivalent to RAND(). */
@LibraryOperator(libraries = {POSTGRESQL})
public static final SqlFunction RANDOM = SqlStdOperatorTable.RAND
.withName("RANDOM")
.withOperandTypeChecker(OperandTypes.NILADIC);
}
52 changes: 0 additions & 52 deletions core/src/main/java/org/apache/calcite/sql/fun/SqlRandFunction.java

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,10 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {

/** The {@code RAND([seed])} function, which yields a random double,
* optionally with seed. */
public static final SqlRandFunction RAND = new SqlRandFunction();
public static final SqlBasicFunction RAND = SqlBasicFunction
.create("RAND", ReturnTypes.DOUBLE,
OperandTypes.NILADIC.or(OperandTypes.NUMERIC), SqlFunctionCategory.NUMERIC)
.withDynamic(true);

/**
* Internal integer arithmetic division operator, '<code>/INT</code>'. This
Expand Down
1 change: 1 addition & 0 deletions site/_docs/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -2815,6 +2815,7 @@ In the following:
| b | PARSE_TIMESTAMP(format, string[, timeZone]) | Uses format specified by *format* to convert *string* representation of timestamp to a TIMESTAMP WITH LOCAL TIME ZONE value in *timeZone*
| h s | PARSE_URL(urlString, partToExtract [, keyToExtract] ) | Returns the specified *partToExtract* from the *urlString*. Valid values for *partToExtract* include HOST, PATH, QUERY, REF, PROTOCOL, AUTHORITY, FILE, and USERINFO. *keyToExtract* specifies which query to extract
| b s | POW(numeric1, numeric2) | Returns *numeric1* raised to the power *numeric2*
| p | RANDOM() | Generates a random double between 0 and 1 inclusive
| s | REGEXP(string, regexp) | Equivalent to `string1 RLIKE string2`
| b | REGEXP_CONTAINS(string, regexp) | Returns whether *string* is a partial match for the *regexp*
| b | REGEXP_EXTRACT(string, regexp [, position [, occurrence]]) | Returns the substring in *string* that matches the *regexp*, starting search at *position* (default 1), and until locating the nth *occurrence* (default 1). Returns NULL if there is no match
Expand Down
16 changes: 16 additions & 0 deletions testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -6359,6 +6359,22 @@ void checkRegexpExtract(SqlOperatorFixture f0, FunctionAlias functionAlias) {
}
}

/** Test case for
* <a href="https://issues.apache.org/jira/browse/CALCITE-6314">[CALCITE-6314]
* Add RANDOM function (enabled in Postgres library)</a>. */
@Test void testRandomFunc() {
final SqlOperatorFixture f = fixture();
f.setFor(SqlLibraryOperators.RANDOM, VmName.EXPAND);
f.checkFails("^random^", "Column 'RANDOM' not found in any table", false);
Consumer<SqlOperatorFixture> consumer = fixture -> {
for (int i = 0; i < 100; i++) {
// Result must always be between 0 and 1, inclusive.
fixture.checkScalarApprox("random()", "DOUBLE NOT NULL", isWithin(0.5, 0.5));
}
};
f.forEachLibrary(list(SqlLibrary.POSTGRESQL), consumer);
}

@Test void testRandIntegerSeedFunc() {
final SqlOperatorFixture f = fixture();
f.setFor(SqlStdOperatorTable.RAND_INTEGER, VmName.EXPAND);
Expand Down

0 comments on commit 9c0d690

Please sign in to comment.