Skip to content

Commit 0e04da2

Browse files
committed
[fix][dingo-calcite] Support operations on tables without primary keys
1 parent f85a117 commit 0e04da2

File tree

21 files changed

+135
-46
lines changed

21 files changed

+135
-46
lines changed

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

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -92,23 +92,6 @@ public double getRowCount() {
9292

9393
@Override
9494
public RelDataType getRowType() {
95-
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
96-
StackTraceElement stackTraceElement = null;
97-
if (stackTrace.length >= 2) {
98-
stackTraceElement = stackTrace[2];
99-
}
100-
DingoTable table = relOptTable.unwrap(DingoTable.class);
101-
if (table == null) {
102-
throw new RuntimeException("getRowType exception, table is null");
103-
}
104-
boolean withoutPri =
105-
table.getTable().getColumns().stream().anyMatch(col -> col.getState() == 2);
106-
if (!withoutPri) {
107-
return relOptTable.getRowType();
108-
}
109-
if (withOutPrimaryRowType(stackTraceElement)) {
110-
return getWithoutPriRowType();
111-
}
11295
return relOptTable.getRowType();
11396
}
11497

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
import java.util.Map;
7171
import java.util.concurrent.ConcurrentHashMap;
7272

73+
import static io.dingodb.common.environment.ExecutionEnvironment.IMPLICT_NAME;
7374
import static org.apache.calcite.util.Static.RESOURCE;
7475

7576
public class DingoSqlValidator extends SqlValidatorImpl {
@@ -338,7 +339,11 @@ public void checkTypeAssignment(
338339

339340
// Fall back to default behavior: compare the type families.
340341
for (int i = 0; i < sourceCount; ++i) {
341-
RelDataType sourceType = sourceFields.get(i).getType();
342+
RelDataTypeField sourceTypeField = sourceFields.get(i);
343+
if (IMPLICT_NAME.equals(sourceTypeField.getName())) {
344+
continue;
345+
}
346+
RelDataType sourceType = sourceTypeField.getType();
342347
RelDataType targetType = targetFields.get(i).getType();
343348
if (!SqlTypeUtil.canAssignFrom(targetType, sourceType)) {
344349
SqlNode node = getNthExpr(query, i, sourceCount);

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

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,6 @@ public class LoadDataExecutor implements DmlExecutor {
107107
private volatile String errMessage;
108108
private Table table;
109109
private final KeyValueCodec codec;
110-
private NavigableMap<ByteArrayUtils.ComparableByteArray, RangeDistribution> distributions;
111110
private final DingoType schema;
112111

113112
MetaService metaService;
@@ -183,7 +182,6 @@ public LoadDataExecutor(
183182
codec = CodecService.getDefault().createKeyValueCodec(
184183
table.getCodecVersion(), table.version, table.tupleType(), table.keyMapping()
185184
);
186-
distributions = metaService.getRangeDistribution(table.tableId);
187185
schema = table.tupleType();
188186
this.isTxn = checkEngine();
189187
this.statementId = UUID.randomUUID().toString();
@@ -445,9 +443,7 @@ private void insertTuples(Object[] tuples) {
445443

446444
public void insertWithoutTxn(Object[] tuples, boolean retry) {
447445
try {
448-
if (retry) {
449-
distributions = metaService.getRangeDistribution(table.tableId);
450-
}
446+
NavigableMap<ByteArrayUtils.ComparableByteArray, RangeDistribution> distributions = metaService.getRangeDistribution(table.tableId);
451447
CommonId partId = PartitionService.getService(
452448
Optional.ofNullable(table.getPartitionStrategy())
453449
.orElse(DingoPartitionServiceProvider.RANGE_FUNC_NAME))

dingo-calcite/src/main/java/io/dingodb/calcite/schema/SubCalciteSchema.java

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -68,19 +68,9 @@ protected SubCalciteSchema(
6868

6969
@Override
7070
public @Nullable TableEntry getImplicitTable(String tableName, boolean caseSensitive) {
71-
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
72-
boolean forValidate = false;
73-
if (stackTrace.length > 19) {
74-
forValidate = stackTrace[19].getMethodName().equalsIgnoreCase("validate");
75-
}
7671
SubSnapshotSchema subSnapshotSchema = (SubSnapshotSchema) schema;
7772
boolean inTxn = subSnapshotSchema.inTransaction();
78-
Table table;
79-
if (forValidate) {
80-
table = ((SubSnapshotSchema) schema).getValidateTable(tableName);
81-
} else {
82-
table = schema.getTable(tableName);
83-
}
73+
Table table = schema.getTable(tableName);
8474
if (table != null && inTxn) {
8575
DingoTable dingoTable = (DingoTable) table;
8676
rootCalciteSchema.putRelatedTable(dingoTable.getTableId().seq, ((SubSnapshotSchema) schema).getSchemaVer());

dingo-calcite/src/main/java/io/dingodb/calcite/utils/RuleUtils.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818

1919
import io.dingodb.calcite.type.DingoSqlTypeFactory;
2020
import io.dingodb.expr.runtime.utils.DateTimeUtils;
21-
import org.apache.calcite.rel.type.RelDataType;
2221
import org.apache.calcite.rex.RexBuilder;
2322
import org.apache.calcite.rex.RexCall;
2423
import org.apache.calcite.rex.RexInputRef;
@@ -34,10 +33,9 @@
3433
import org.checkerframework.checker.nullness.qual.Nullable;
3534

3635
import java.sql.Date;
37-
import java.sql.Time;
3836
import java.sql.Timestamp;
3937
import java.util.Calendar;
40-
import java.util.Objects;
38+
import java.util.TimeZone;
4139

4240
public class RuleUtils {
4341

@@ -114,6 +112,7 @@ private static boolean checkConditionOp(@NonNull RexNode op0, RexNode op1, Condi
114112
}
115113
Calendar calendar = Calendar.getInstance();
116114
calendar.setTimeInMillis(timestamp.getTime());
115+
calendar.setTimeZone(TimeZone.getTimeZone("UTC"));
117116
TimestampString timestampString = TimestampString.fromCalendarFields(calendar);
118117
info.index = ((RexInputRef) op0).getIndex();
119118
info.value = rexBuilder.makeTimestampLiteral(timestampString, 19);

dingo-calcite/src/main/java/org/apache/calcite/sql/validate/implicit/DingoTypeCoercionImpl.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
import java.util.List;
4646

4747
import static io.dingodb.calcite.DingoTypeMapper.getAggregateResultType;
48+
import static io.dingodb.common.environment.ExecutionEnvironment.IMPLICT_NAME;
4849
import static org.apache.calcite.linq4j.Nullness.castNonNull;
4950

5051
@Slf4j
@@ -59,7 +60,11 @@ public DingoTypeCoercionImpl(RelDataTypeFactory typeFactory, SqlValidator valida
5960
final List<RelDataTypeField> targetFields = targetRowType.getFieldList();
6061
final int sourceCount = sourceFields.size();
6162
for (int i = 0; i < sourceCount; i++) {
62-
RelDataType sourceType = sourceFields.get(i).getType();
63+
RelDataTypeField sourceTypeField = sourceFields.get(i);
64+
if (IMPLICT_NAME.equals(sourceTypeField.getName())) {
65+
continue;
66+
}
67+
RelDataType sourceType = sourceTypeField.getType();
6368
RelDataType targetType = targetFields.get(i).getType();
6469
if (!SqlTypeUtil.equalSansNullability(validator.getTypeFactory(), sourceType, targetType)
6570
&& !SqlTypeUtil.canCastFrom(targetType, sourceType, true)) {
@@ -83,6 +88,10 @@ public DingoTypeCoercionImpl(RelDataTypeFactory typeFactory, SqlValidator valida
8388
}
8489
boolean coerced = false;
8590
for (int i = 0; i < sourceFields.size(); i++) {
91+
RelDataTypeField sourceTypeField = sourceFields.get(i);
92+
if (IMPLICT_NAME.equals(sourceTypeField.getName())) {
93+
continue;
94+
}
8695
RelDataType targetType = targetFields.get(i).getType();
8796
coerced = coerceSourceRowType1(scope, query, i, targetType) || coerced;
8897
}

dingo-codec-api/src/main/java/io/dingodb/codec/KeyValueCodec.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package io.dingodb.codec;
1818

1919
import io.dingodb.common.store.KeyValue;
20+
import io.dingodb.common.type.DingoType;
2021
import org.checkerframework.checker.nullness.qual.NonNull;
2122

2223
public interface KeyValueCodec {
@@ -72,4 +73,6 @@ public interface KeyValueCodec {
7273
default Object[] mapKeyAndDecodeValue(Object[] keys, byte[] bytes) {
7374
throw new UnsupportedOperationException();
7475
}
76+
77+
default DingoType getDingoType() { return null; }
7578
}

dingo-common/src/main/java/io/dingodb/common/environment/ExecutionEnvironment.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ public class ExecutionEnvironment {
4646
public MdlCheckTableInfo mdlCheckTableInfo = new MdlCheckTableInfo();
4747

4848
public ClientIdentity clientIdentity = new ClientIdentity();
49+
public static final String IMPLICT_NAME = "_ROWID";
4950

5051
public volatile long safePointTs;
5152

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,4 +119,8 @@ public interface DingoType extends CompileContext {
119119
default void setHidden(boolean hidden){};
120120

121121
default boolean isHidden() { return false; };
122+
123+
default void setCheckFieldCount(boolean check) {};
124+
125+
default boolean checkFieldCount() { return true; }
122126
}

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

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,18 @@ public class TupleType extends AbstractDingoType {
4444
@Getter
4545
private final Type type;
4646

47+
// create table b(id int,age int);
48+
// When executing insert into tab select * from b on a table without a primary key,
49+
// the hidden primary key is found but the target table does not have the relevant schema.
50+
// In this case, the fieldCount and tuple. length are inconsistent, No need to check
51+
// example: TxnPartInsertOperator,TxnPartInsertIgnoreOperator
52+
public boolean checkFieldCount;
53+
54+
@Override
55+
public void setCheckFieldCount(boolean checkFieldCount) {
56+
this.checkFieldCount = checkFieldCount;
57+
}
58+
4759
@JsonCreator
4860
public TupleType(
4961
@JsonProperty("fields") DingoType[] fields
@@ -65,6 +77,7 @@ public TupleType(
6577
}
6678
}
6779
).toArray(Type[]::new));
80+
this.checkFieldCount = true;
6881
}
6982

7083
private void setElementIds() {
@@ -96,7 +109,15 @@ public int fieldCount() {
96109

97110
@Override
98111
public DingoType getChild(@NonNull Object index) {
99-
return fields[(int) index];
112+
int idx = (int) index;
113+
if (idx < fieldCount()) {
114+
return fields[(int) index];
115+
} else {
116+
// When executing insert into tab select * from without PrimaryTab on a table without a primary key,
117+
// the hidden primary key is found but the target table does not have the relevant schema
118+
// set type = null
119+
return null;
120+
}
100121
}
101122

102123
@Override
@@ -169,11 +190,16 @@ public String toString() {
169190
}
170191

171192
private Object @NonNull [] checkFieldCount(Object @NonNull [] tuple) {
172-
if (tuple.length == fieldCount()) {
193+
if (checkFieldCount) {
194+
if (tuple.length == fieldCount()) {
195+
return tuple;
196+
} else {
197+
throw new IllegalArgumentException(
198+
"Required " + fieldCount() + " elements, but " + tuple.length + " provided."
199+
);
200+
}
201+
} else {
173202
return tuple;
174203
}
175-
throw new IllegalArgumentException(
176-
"Required " + fieldCount() + " elements, but " + tuple.length + " provided."
177-
);
178204
}
179205
}

0 commit comments

Comments
 (0)