Skip to content

Commit 0d2e444

Browse files
committed
[fix][dingo-calcite] Add data validation when modifying table columns
1 parent 6524907 commit 0d2e444

File tree

20 files changed

+314
-66
lines changed

20 files changed

+314
-66
lines changed

dingo-calcite/src/main/java/io/dingodb/calcite/DingoDdlExecutor.java

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,9 @@
109109
import io.dingodb.common.type.DingoType;
110110
import io.dingodb.common.type.ListType;
111111
import io.dingodb.common.type.MapType;
112+
import io.dingodb.common.type.TupleType;
113+
import io.dingodb.common.type.converter.DingoConverter;
114+
import io.dingodb.common.type.converter.StrParseConverter;
112115
import io.dingodb.common.type.scalar.BinaryType;
113116
import io.dingodb.common.type.scalar.BitType;
114117
import io.dingodb.common.type.scalar.BooleanType;
@@ -2122,6 +2125,9 @@ public static void validatePartitionBy(
21222125
throw DingoErrUtil.newStdErr("part column must be primary key");
21232126
}
21242127
}
2128+
if ("range".equalsIgnoreCase(partDefinition.getFuncName())) {
2129+
checkOperandType(tableDefinition, partDefinition);
2130+
}
21252131
}
21262132

21272133
List<PartitionDetailDefinition> details = new ArrayList<>();
@@ -2134,6 +2140,39 @@ public static void validatePartitionBy(
21342140
partDefinition.setDetails(details);
21352141
}
21362142

2143+
private static void checkOperandType(@NonNull TableDefinition tableDefinition, PartitionDefinition partDefinition) {
2144+
DingoType keysType = tableDefinition.getKeyType();
2145+
if (keysType instanceof TupleType) {
2146+
TupleType keysType1 = (TupleType) keysType;
2147+
partDefinition.getDetails().forEach(detail -> {
2148+
if (detail.getOperand() == null) {
2149+
return;
2150+
}
2151+
Object[] operand = detail.getOperand();
2152+
if (detail.getOperand().length > keysType1.fieldCount()) {
2153+
throw new IllegalArgumentException(
2154+
"Partition values count must be <= key columns count, but values count is "
2155+
+ detail.getOperand().length
2156+
);
2157+
}
2158+
for (int i = 0; i < operand.length; i++) {
2159+
DingoType type = keysType1.getChild(i);
2160+
if (operand[i] != null) {
2161+
Object object = type.convertTo(type.convertFrom(operand[i].toString(),
2162+
StrParseConverter.INSTANCE),
2163+
DingoConverter.INSTANCE);
2164+
if (object == null) {
2165+
throw new IllegalArgumentException(
2166+
"For input string \""
2167+
+ operand[i] + "\""
2168+
);
2169+
}
2170+
}
2171+
}
2172+
});
2173+
}
2174+
}
2175+
21372176
@NonNull
21382177
private static PrivilegeDefinition getPrivilegeDefinition(
21392178
@NonNull SqlGrant sqlGrant, CalcitePrepare.@NonNull Context context

dingo-calcite/src/main/java/io/dingodb/calcite/DingoParser.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
import io.dingodb.calcite.grammar.ddl.SqlTruncate;
6666
import io.dingodb.calcite.grammar.ddl.SqlUnLockBlock;
6767
import io.dingodb.calcite.grammar.ddl.SqlUnLockTable;
68+
import io.dingodb.calcite.grammar.ddl.SqlUseSchema;
6869
import io.dingodb.calcite.grammar.dml.SqlExecute;
6970
import io.dingodb.calcite.grammar.dml.SqlInsert;
7071
import io.dingodb.calcite.grammar.dml.SqlPrepare;
@@ -508,7 +509,8 @@ protected static boolean compatibleMysql(SqlNode sqlNode, PlanProfile planProfil
508509
|| sqlNode instanceof SqlBackUpTimePoint
509510
|| sqlNode instanceof SqlBackUpTsoPoint
510511
|| sqlNode instanceof SqlTsoToTime
511-
|| sqlNode instanceof SqlTenantsBackUpTimePoint;
512+
|| sqlNode instanceof SqlTenantsBackUpTimePoint
513+
|| sqlNode instanceof SqlUseSchema;
512514
}
513515
}
514516

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* Copyright 2021 DataCanvas
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.dingodb.calcite.executor;
18+
19+
import io.dingodb.tool.api.QueryManager;
20+
21+
import java.sql.Connection;
22+
23+
public class InitSchemaExecutor implements DdlExecutor {
24+
25+
private final Connection connection;
26+
27+
private final String schema;
28+
29+
public InitSchemaExecutor(Connection connection, String schema) {
30+
this.connection = connection;
31+
this.schema = schema;
32+
}
33+
34+
@Override
35+
public void execute() {
36+
QueryManager.getDefault().initSchema(connection, schema);
37+
}
38+
}

dingo-calcite/src/main/java/io/dingodb/calcite/executor/SqlToExecutorConverter.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import io.dingodb.calcite.grammar.ddl.SqlRollback;
3232
import io.dingodb.calcite.grammar.ddl.SqlUnLockBlock;
3333
import io.dingodb.calcite.grammar.ddl.SqlUnLockTable;
34+
import io.dingodb.calcite.grammar.ddl.SqlUseSchema;
3435
import io.dingodb.calcite.grammar.dql.SqlBackUpTimePoint;
3536
import io.dingodb.calcite.grammar.dql.SqlBackUpTsoPoint;
3637
import io.dingodb.calcite.grammar.dql.SqlDescTable;
@@ -284,6 +285,9 @@ public static Optional<Executor> convert(SqlNode sqlNode, Connection connection,
284285
} else if (sqlNode instanceof SqlShowExecutorVariables) {
285286
SqlShowExecutorVariables sqlShowExecutorVariables = (SqlShowExecutorVariables) sqlNode;
286287
return Optional.of(new ShowExecutorVariablesExecutor(sqlShowExecutorVariables.sqlLikePattern));
288+
} else if (sqlNode instanceof SqlUseSchema) {
289+
SqlUseSchema sqlUseSchema = (SqlUseSchema) sqlNode;
290+
return Optional.of(new InitSchemaExecutor(connection, sqlUseSchema.schema));
287291
} else {
288292
return Optional.empty();
289293
}

dingo-calcite/src/main/java/io/dingodb/calcite/rel/DingoGetByIndex.java

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -175,12 +175,17 @@ public double estimateRowCount(RelMetadataQuery mq) {
175175
}
176176
Table indexTd = getIndexTdMap().get(commonId);
177177
Table td = Objects.requireNonNull(getTable().unwrap(DingoTable.class)).getTable();
178-
List<Integer> indexSelectionList = td.getColumnIndices2(indexTd.getColumns());
179-
Mapping mapping = Mappings.target(indexSelectionList, td.getColumns().size());
180-
Pair<RexNode, RexNode> res = DingoFilterUtils.splitRexFilter(filter, mapping, getCluster().getRexBuilder());
181178
RexNode indexFilter;
182-
if (res != null && res.getKey() != null) {
183-
indexFilter = res.getKey();
179+
if (lookup) {
180+
List<Integer> indexSelectionList = td.getColumnIndices2(indexTd.getColumns());
181+
Mapping mapping = Mappings.target(indexSelectionList, td.getColumns().size());
182+
Pair<RexNode, RexNode> res = DingoFilterUtils.splitRexFilter(filter, mapping, getCluster().getRexBuilder());
183+
184+
if (res != null && res.getKey() != null) {
185+
indexFilter = res.getKey();
186+
} else {
187+
indexFilter = filter;
188+
}
184189
} else {
185190
indexFilter = filter;
186191
}

dingo-calcite/src/main/java/io/dingodb/calcite/rule/DingoIndexNonLeftMatchRule.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@
7575
import static org.apache.calcite.sql.SqlKind.IS_NULL;
7676
import static org.apache.calcite.sql.SqlKind.LESS_THAN;
7777
import static org.apache.calcite.sql.SqlKind.LESS_THAN_OR_EQUAL;
78+
import static org.apache.calcite.sql.SqlKind.OR;
7879

7980
@Slf4j
8081
@Value.Enclosing
@@ -85,7 +86,7 @@ public class DingoIndexNonLeftMatchRule extends RelRule<DingoIndexNonLeftMatchRu
8586
IN, EQUALS, AND,
8687
LESS_THAN, GREATER_THAN,
8788
GREATER_THAN_OR_EQUAL, LESS_THAN_OR_EQUAL,
88-
IS_NULL);
89+
IS_NULL, OR);
8990

9091
protected DingoIndexNonLeftMatchRule(Config config) {
9192
super(config);
@@ -273,6 +274,9 @@ private static RelNode getIndexFullScanRelNode(LogicalProject project, LogicalDi
273274
}
274275
return null;
275276
}
277+
if (scan.getFilter().isA(OR)) {
278+
return null;
279+
}
276280
LogicalIndexFullScan indexFullScan = new LogicalIndexFullScan(
277281
scan.getCluster(),
278282
scan.getTraitSet(),

dingo-common/src/main/java/io/dingodb/common/ddl/DdlJob.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
import io.dingodb.common.mysql.DingoErr;
2626
import io.dingodb.common.partition.PartitionDetailDefinition;
2727
import io.dingodb.common.sequence.SequenceDefinition;
28-
import io.dingodb.common.table.ColumnDefinition;
2928
import io.dingodb.common.table.IndexDefinition;
3029
import io.dingodb.common.table.TableDefinition;
3130
import lombok.Builder;

dingo-common/src/main/java/io/dingodb/common/mysql/error/ErrorMessage.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ public final class ErrorMessage {
6363
+ "this is incompatible with sql_mode=only_full_group_by");
6464
errorMap.put(ErrMixOfGroupFuncAndFields, "In aggregated query without GROUP BY, expression #%d of "
6565
+ "SELECT list contains nonaggregated column '%s'; this is incompatible with sql_mode=only_full_group_by");
66+
errorMap.put(ErrWarnDataOutOfRange, "Out of range value for column 'age' at row 1");
6667
}
6768

6869
private ErrorMessage() {

dingo-common/src/main/java/io/dingodb/common/session/SessionUtil.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,18 +94,19 @@ public String exeUpdateInTxn(String sql, int retry) {
9494
}
9595
}
9696

97-
public long exeUpdate(String sql, int retry) throws Exception {
97+
public long exeUpdate(String sql, int retry, String schema) throws Exception {
9898
Session session = null;
9999
try {
100100
session = getSession();
101+
session.executeUpdate("use " + schema);
101102
return session.executeUpdate1(sql);
102103
} catch (Exception e) {
103104
LogUtils.error(log, e.getMessage());
104105
retry --;
105106
if (retry == 0) {
106107
throw e;
107108
} else {
108-
return exeUpdate(sql, retry);
109+
return exeUpdate(sql, retry, schema);
109110
}
110111
} finally {
111112
closeSession(session);

dingo-common/src/main/java/io/dingodb/common/type/DingoTypeFactory.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import io.dingodb.common.type.scalar.StringType;
3131
import io.dingodb.common.type.scalar.TimeType;
3232
import io.dingodb.common.type.scalar.TimestampType;
33+
import io.dingodb.common.type.scalar.TinyIntType;
3334
import io.dingodb.expr.common.type.Type;
3435
import lombok.extern.slf4j.Slf4j;
3536
import org.checkerframework.checker.nullness.qual.NonNull;
@@ -51,7 +52,7 @@ public final class DingoTypeFactory {
5152
private DingoTypeFactory() {
5253
scalarGenerators = new TreeMap<>(String::compareToIgnoreCase);
5354
intervalGenerators = new TreeMap<>(String::compareToIgnoreCase);
54-
scalarGenerators.put("TINYINT", IntegerType::new);
55+
scalarGenerators.put("TINYINT", TinyIntType::new);
5556
scalarGenerators.put("INT", IntegerType::new);
5657
scalarGenerators.put("INTEGER", IntegerType::new);
5758
scalarGenerators.put("LONG", LongType::new);

0 commit comments

Comments
 (0)