Skip to content

Remove redundancy by using ANY parameter for IS TYPE operators #1321

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jan 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -403,68 +403,61 @@ internal object PartiQLHeader : Header() {
// To model type assertion, generating a list of assertion function based on the type,
// and the parameter will be the value entered.
// i.e., 1 is INT2 => is_int16(1)
private fun isType(): List<FunctionSignature.Scalar> = types.all.filterNot { it == NULL || it == MISSING }.flatMap { element ->
types.all.filterNot { it == MISSING || it == ANY }.map { operand ->
private fun isType(): List<FunctionSignature.Scalar> =
types.all.filterNot { it == NULL || it == MISSING }.map { element ->
FunctionSignature.Scalar(
name = "is_${element.name.lowercase()}",
returns = BOOL,
parameters = listOf(
FunctionParameter("value", operand)
FunctionParameter("value", ANY)
),
isNullCall = false, // TODO: Should this be true?
isNullable = false
isNullable = false,
isNullCall = false,
)
}
}

// In type assertion, it is possible for types to have args
// i.e., 'a' is CHAR(2)
// we put type parameter before value.
private fun isTypeSingleArg(): List<FunctionSignature.Scalar> = listOf(CHAR, STRING).flatMap { element ->
types.all.filterNot { it == MISSING }.map { operand ->
FunctionSignature.Scalar(
name = "is_${element.name.lowercase()}",
returns = BOOL,
parameters = listOf(
FunctionParameter("type_parameter_1", INT32),
FunctionParameter("value", operand)
),
isNullable = false, // TODO: Should this be true?
isNullCall = false
)
}
private fun isTypeSingleArg(): List<FunctionSignature.Scalar> = listOf(CHAR, STRING).map { element ->
FunctionSignature.Scalar(
name = "is_${element.name.lowercase()}",
returns = BOOL,
parameters = listOf(
FunctionParameter("type_parameter_1", INT32),
FunctionParameter("value", ANY)
),
isNullable = false,
isNullCall = false
)
}

private fun isTypeDoubleArgsInt(): List<FunctionSignature.Scalar> = listOf(DECIMAL).flatMap { element ->
types.all.filterNot { it == MISSING }.map { operand ->
FunctionSignature.Scalar(
name = "is_${element.name.lowercase()}",
returns = BOOL,
parameters = listOf(
FunctionParameter("type_parameter_1", INT32),
FunctionParameter("type_parameter_2", INT32),
FunctionParameter("value", operand)
),
isNullable = false,
isNullCall = false
)
}
private fun isTypeDoubleArgsInt(): List<FunctionSignature.Scalar> = listOf(DECIMAL).map { element ->
FunctionSignature.Scalar(
name = "is_${element.name.lowercase()}",
returns = BOOL,
parameters = listOf(
FunctionParameter("type_parameter_1", INT32),
FunctionParameter("type_parameter_2", INT32),
FunctionParameter("value", ANY)
),
isNullable = false,
isNullCall = false
)
}

private fun isTypeTime(): List<FunctionSignature.Scalar> = listOf(TIME, TIMESTAMP).flatMap { element ->
types.all.filterNot { it == MISSING }.map { operand ->
FunctionSignature.Scalar(
name = "is_${element.name.lowercase()}",
returns = BOOL,
parameters = listOf(
FunctionParameter("type_parameter_1", BOOL),
FunctionParameter("type_parameter_2", INT32),
FunctionParameter("value", operand) // TODO: Decide if we need to further segment this
),
isNullCall = false,
isNullable = false
)
}
private fun isTypeTime(): List<FunctionSignature.Scalar> = listOf(TIME, TIMESTAMP).map { element ->
FunctionSignature.Scalar(
name = "is_${element.name.lowercase()}",
returns = BOOL,
parameters = listOf(
FunctionParameter("type_parameter_1", BOOL),
FunctionParameter("type_parameter_2", INT32),
FunctionParameter("value", ANY) // TODO: Decide if we need to further segment this
),
isNullable = false,
isNullCall = false
)
}

// SUBSTRING (expression, start[, length]?)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,66 @@ class PlanTyperTestsPorted {
),
)

@JvmStatic
fun isTypeCases() = listOf(
SuccessTestCase(
name = "IS BOOL",
key = key("is-type-00"),
catalog = "pql",
catalogPath = listOf("main"),
expected = StaticType.BOOL
),
SuccessTestCase(
name = "IS INT",
key = key("is-type-01"),
catalog = "pql",
catalogPath = listOf("main"),
expected = StaticType.BOOL
),
SuccessTestCase(
name = "IS STRING",
key = key("is-type-02"),
catalog = "pql",
catalogPath = listOf("main"),
expected = StaticType.BOOL
),
SuccessTestCase(
name = "IS NULL",
key = key("is-type-03"),
catalog = "pql",
expected = StaticType.BOOL,
),
SuccessTestCase(
name = "MISSING IS NULL",
key = key("is-type-04"),
catalog = "pql",
expected = StaticType.BOOL,
),
SuccessTestCase(
name = "NULL IS NULL",
key = key("is-type-05"),
catalog = "pql",
expected = StaticType.BOOL,
),
SuccessTestCase(
name = "MISSING IS MISSING",
key = key("is-type-06"),
catalog = "pql",
expected = StaticType.BOOL,
),
SuccessTestCase(
name = "NULL IS MISSING",
key = key("is-type-07"),
catalog = "pql",
expected = StaticType.BOOL,
),
ErrorTestCase(
name = "ERROR always MISSING",
key = key("is-type-08"),
catalog = "pql",
),
)

@JvmStatic
fun sessionVariables() = listOf(
SuccessTestCase(
Expand Down Expand Up @@ -536,7 +596,10 @@ class PlanTyperTestsPorted {
problemHandler = assertProblemExists {
Problem(
UNKNOWN_PROBLEM_LOCATION,
PlanningProblemDetails.UnknownFunction("bitwise_and", listOf(StaticType.INT4, StaticType.STRING))
PlanningProblemDetails.UnknownFunction(
"bitwise_and",
listOf(StaticType.INT4, StaticType.STRING)
)
)
}
),
Expand Down Expand Up @@ -2972,6 +3035,11 @@ class PlanTyperTestsPorted {
@Execution(ExecutionMode.CONCURRENT)
fun testPivot(tc: TestCase) = runTest(tc)

@ParameterizedTest
@MethodSource("isTypeCases")
@Execution(ExecutionMode.CONCURRENT)
fun testIsType(tc: TestCase) = runTest(tc)

// --------- Finish Parameterized Tests ------

//
Expand All @@ -2980,7 +3048,7 @@ class PlanTyperTestsPorted {
private fun infer(
query: String,
session: PartiQLPlanner.Session,
problemCollector: ProblemCollector
problemCollector: ProblemCollector,
): PartiQLPlan {
val ast = parser.parse(query).root
return planner.plan(ast, session, problemCollector).plan
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
--#[is-type-00]
false IS BOOL;

--#[is-type-01]
item.i_class_id IS INT;

--#[is-type-02]
item.i_brand IS STRING;

--#[is-type-03]
1 IS NULL;

--#[is-type-04]
MISSING IS NULL;

--#[is-type-05]
NULL IS NULL;

--#[is-type-06]
MISSING IS MISSING;

--#[is-type-07]
NULL IS MISSING;

--#[is-type-08]
-- ERROR! always MISSING
MISSING IS BOOL;