Skip to content
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

IGNITE-23414 : Calcite. Fix cast of dynamic parameters v2. #11787

Open
wants to merge 52 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 41 commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
91d6e24
raw
Vladsz83 Oct 7, 2024
468de5f
Merge branch 'master' into IGNITE-23361_Calcite._Lost_precision_of_dy…
Vladsz83 Oct 7, 2024
93bf93b
raw
Vladsz83 Oct 7, 2024
6f188de
alpha
Vladsz83 Oct 8, 2024
30caf38
impl
Vladsz83 Oct 9, 2024
abf0734
manual review
Vladsz83 Oct 9, 2024
f176d69
reimpl
Vladsz83 Oct 9, 2024
957b4fb
reimpl tested
Vladsz83 Oct 9, 2024
a857b74
test fix
Vladsz83 Oct 11, 2024
4af91df
Merge branch 'master' into IGNITE-23361_Calcite._Lost_precision_of_dy…
Vladsz83 Oct 18, 2024
3a68a19
Merge branch 'master' into IGNITE-23361_Calcite._Lost_precision_of_dy…
Vladsz83 Oct 18, 2024
1c69c5a
fix
Vladsz83 Oct 18, 2024
79e51ab
review fixex
Vladsz83 Oct 18, 2024
fe07143
review fix
Vladsz83 Oct 18, 2024
0340a88
review fix
Vladsz83 Oct 18, 2024
379da24
Merge branch 'master' into IGNITE-23361_Calcite._Lost_precision_of_dy…
Vladsz83 Oct 21, 2024
4896715
fix
Vladsz83 Oct 21, 2024
394ee9c
research
Vladsz83 Oct 22, 2024
c0fe968
research
Vladsz83 Oct 23, 2024
8d009cc
alpha
Vladsz83 Oct 23, 2024
6f2816b
alpha
Vladsz83 Oct 23, 2024
d0fb31d
test fixes
Vladsz83 Oct 24, 2024
ba7064e
Merge branch 'master' into IGNITE-23414-Calcite._Fix_cast_of_dynamic_…
Vladsz83 Oct 24, 2024
b2f8939
test fixes
Vladsz83 Oct 24, 2024
90b1c9e
Merge branch 'master' into IGNITE-23414-Calcite._Fix_cast_of_dynamic_…
Vladsz83 Oct 24, 2024
f4870ec
merged master, commited tests
Vladsz83 Oct 24, 2024
da8c97f
raw
Vladsz83 Oct 25, 2024
1cb9423
before full tests
Vladsz83 Oct 25, 2024
e191016
uncommited some tests
Vladsz83 Oct 25, 2024
791f9e3
removed params check, restored tests
Vladsz83 Oct 25, 2024
8c82a35
Merge branch 'master' into IGNITE-23414-Calcite._Fix_cast_of_dynamic_…
Vladsz83 Oct 29, 2024
36e752b
merged master
Vladsz83 Oct 29, 2024
44f4f94
Merge branch 'master' into IGNITE-23414-Calcite._Fix_cast_of_dynamic_…
Vladsz83 Dec 24, 2024
a8b7557
Merge branch 'master' into IGNITE-23414-Calcite._Fix_cast_of_dynamic_…
Vladsz83 Dec 28, 2024
b15aa3b
impl
Vladsz83 Dec 28, 2024
dfaa670
fix
Vladsz83 Dec 28, 2024
d8933a7
fix
Vladsz83 Dec 28, 2024
d30c9b9
Merge remote-tracking branch 'my/IGNITE-23414-Calcite._Fix_cast_of_dy…
Vladsz83 Dec 28, 2024
2669622
revert test
Vladsz83 Dec 28, 2024
c499415
trivial comment
Vladsz83 Dec 28, 2024
0826926
spell fix
Vladsz83 Dec 28, 2024
4310202
checkstyle fix
Vladsz83 Dec 29, 2024
227b162
test fix 1
Vladsz83 Dec 30, 2024
292eab4
Merge branch 'master' into IGNITE-23414-Calcite._Fix_cast_of_dynamic_…
Vladsz83 Dec 30, 2024
74300fc
research
Vladsz83 Jan 9, 2025
0c6eda7
test fixes
Vladsz83 Jan 9, 2025
2356ffe
revert research
Vladsz83 Jan 9, 2025
175f0c3
revert test
Vladsz83 Jan 9, 2025
6c70991
revert
Vladsz83 Jan 9, 2025
5e05aaa
revert
Vladsz83 Jan 9, 2025
1de9435
Fix
Vladsz83 Jan 9, 2025
813244b
Revert "Fix"
Vladsz83 Jan 9, 2025
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 @@ -70,6 +70,7 @@
import org.apache.ignite.internal.processors.query.calcite.schema.IgniteTable;
import org.apache.ignite.internal.processors.query.calcite.sql.IgniteSqlDecimalLiteral;
import org.apache.ignite.internal.processors.query.calcite.type.IgniteTypeFactory;
import org.apache.ignite.internal.processors.query.calcite.type.OtherType;
import org.apache.ignite.internal.processors.query.calcite.util.IgniteResource;
import org.apache.ignite.internal.util.typedef.F;
import org.jetbrains.annotations.Nullable;
Expand Down Expand Up @@ -102,20 +103,25 @@ public class IgniteSqlValidator extends SqlValidatorImpl {
}

/** Dynamic parameters. */
Object[] parameters;
@Nullable private final Object[] parameters;

/**
* Creates a validator.
*
* @param opTab Operator table
* @param catalogReader Catalog reader
* @param typeFactory Type factory
* @param config Config
* @param cfg Config
* @param parameters Dynamic parameters
*/
public IgniteSqlValidator(SqlOperatorTable opTab, CalciteCatalogReader catalogReader,
IgniteTypeFactory typeFactory, SqlValidator.Config config, Object[] parameters) {
super(opTab, catalogReader, typeFactory, config);
public IgniteSqlValidator(
SqlOperatorTable opTab,
CalciteCatalogReader catalogReader,
IgniteTypeFactory typeFactory,
SqlValidator.Config cfg,
@Nullable Object[] parameters
) {
super(opTab, catalogReader, typeFactory, cfg);

this.parameters = parameters;
}
Expand Down Expand Up @@ -534,9 +540,44 @@ private boolean isSystemFieldName(String alias) {
|| QueryUtils.VAL_FIELD_NAME.equalsIgnoreCase(alias);
}

/** {@inheritDoc} */
@Override public RelDataType deriveType(SqlValidatorScope scope, SqlNode expr) {
if (expr instanceof SqlDynamicParam) {
RelDataType type = deriveDynamicParameterType((SqlDynamicParam)expr);

if (type != null)
return type;
}

return super.deriveType(scope, expr);
}

/** @return A derived type or {@code null} if unable to determine. */
@Nullable private RelDataType deriveDynamicParameterType(SqlDynamicParam node) {
RelDataType type = getValidatedNodeTypeIfKnown(node);

// Do not clarify the widest type for any value.
if (type instanceof OtherType)
return type;

if (parameters == null || node.getIndex() >= parameters.length)
return null;

Object val = parameters[node.getIndex()];

type = val == null
? typeFactory.createSqlType(SqlTypeName.NULL)
: typeFactory().createTypeWithNullability(typeFactory().toSql(typeFactory().createType(val.getClass())), true);

setValidatedNodeType(node, type);

return type;
}


/** {@inheritDoc} */
@Override protected void inferUnknownTypes(RelDataType inferredType, SqlValidatorScope scope, SqlNode node) {
if (inferDynamicParamType(inferredType, node))
if (node instanceof SqlDynamicParam && unknownType.equals(inferredType) && deriveDynamicParameterType((SqlDynamicParam)node) != null)
return;

if (node instanceof SqlCall) {
Expand Down Expand Up @@ -583,40 +624,6 @@ else if (operandTypeChecker instanceof FamilyOperandTypeChecker) {
super.inferUnknownTypes(inferredType, scope, node);
}

/**
* Tries to set actual type of dynamic parameter if {@code node} is a {@link SqlDynamicParam} and if its index
* is actual to {@link #parameters}.
*
* @return {@code True} if a new type was set. {@code False} otherwise.
*/
private boolean inferDynamicParamType(RelDataType inferredType, SqlNode node) {
if (parameters == null || !(node instanceof SqlDynamicParam) || ((SqlDynamicParam)node).getIndex() >= parameters.length)
return false;

Object val = parameters[((SqlDynamicParam)node).getIndex()];

if (val == null) {
if (inferredType.equals(unknownType)) {
setValidatedNodeType(node, typeFactory().createSqlType(SqlTypeName.NULL));

return true;
}

return false;
}

RelDataType valType = typeFactory().toSql(typeFactory().createType(val.getClass()));

assert !unknownType.equals(valType);

if (unknownType.equals(inferredType) || valType.getFamily().equals(inferredType.getFamily()))
setValidatedNodeType(node, valType);
else
setValidatedNodeType(node, inferredType);

return true;
}

/** {@inheritDoc} */
@Override public SqlLiteral resolveLiteral(SqlLiteral literal) {
if (literal instanceof SqlNumericLiteral && literal.createSqlType(typeFactory).getSqlTypeName() == SqlTypeName.BIGINT) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import org.apache.ignite.internal.processors.query.calcite.type.IgniteTypeFactory;
import org.apache.ignite.internal.util.typedef.internal.U;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

/**
* Planning context.
Expand All @@ -45,7 +46,7 @@ public final class PlanningContext implements Context {
private final String qry;

/** */
private final Object[] parameters;
@Nullable private final Object[] parameters;

/** */
private final CancelFlag cancelFlag = new CancelFlag(new AtomicBoolean());
Expand All @@ -68,7 +69,7 @@ public final class PlanningContext implements Context {
private PlanningContext(
Context parentCtx,
String qry,
Object[] parameters,
@Nullable Object[] parameters,
long plannerTimeout
) {
this.qry = qry;
Expand All @@ -90,7 +91,7 @@ public String query() {
* @return Query parameters.
*/
@SuppressWarnings("AssignmentOrReturnOfFieldWithMutableType")
public Object[] parameters() {
@Nullable public Object[] parameters() {
return parameters;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
import java.time.Period;
import java.util.List;
import java.util.UUID;
import org.apache.ignite.IgniteCache;
import org.apache.ignite.internal.processors.query.IgniteSQLException;
import org.apache.ignite.internal.util.typedef.F;
import org.junit.Test;

Expand Down Expand Up @@ -60,6 +62,44 @@ public void testMetadataTypesForDynamicParameters() {
}
}

/** */
@Test
public void testMissedValue() {
assertThrows("SELECT ?", IgniteSQLException.class, "Illegal use of dynamic parameter");

assertThrows("SELECT ?, ?", IgniteSQLException.class, "Illegal use of dynamic parameter", "arg0");
}

/** */
@Test
public void testCasts() {
assertQuery("SELECT CAST(? as INTEGER)").withParams('1').returns(1).check();
assertQuery("SELECT ?::INTEGER").withParams('1').returns(1).check();
assertQuery("SELECT ?::VARCHAR").withParams(1).returns("1").check();
assertQuery("SELECT CAST(? as VARCHAR)").withParams(1).returns("1").check();

IgniteCache<Integer, Employer> cache = createAndPopulateTable();

cache.put(cache.size(), new Employer("15", 15d));

assertQuery("SELECT name FROM Person WHERE id=?::INTEGER").withParams("2").returns("Ilya").check();
assertQuery("SELECT name FROM Person WHERE id=CAST(? as INTEGER)").withParams("2").returns("Ilya").check();

assertQuery("SELECT id FROM Person WHERE name=CAST(? as VARCHAR)").withParams(15).returns(5).check();
assertQuery("SELECT id FROM Person WHERE name IN (?::VARCHAR)").withParams(15).returns(5).check();
assertQuery("SELECT name FROM Person WHERE id IN (?::INTEGER)").withParams("2").returns("Ilya").check();
assertQuery("SELECT name FROM Person WHERE id IN (?::INTEGER, ?::INTEGER)").withParams("2", "3")
.returns("Ilya").returns("Roma").check();

assertQuery("SELECT count(*) FROM Person WHERE ? IS NOT NULL").withParams(1).returns(6L).check();
assertQuery("SELECT count(*) FROM Person WHERE ? IS NOT NULL").withParams("abc").returns(6L).check();
assertQuery("SELECT count(*) FROM Person WHERE ? IS NOT NULL").withParams(new Object[] { null }).returns(0L).check();

assertQuery("SELECT count(*) FROM Person WHERE ? IS NULL").withParams(1).returns(0L).check();
assertQuery("SELECT count(*) FROM Person WHERE ? IS NULL").withParams("abc").returns(0L).check();
assertQuery("SELECT count(*) FROM Person WHERE ? IS NULL").withParams(new Object[] {null}).returns(6L).check();
}

/** */
@Test
public void testDynamicParameters() {
Expand Down