Skip to content
Closed
4 changes: 4 additions & 0 deletions fe/fe-core/src/main/java/org/apache/doris/analysis/Analyzer.java
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -656,6 +656,10 @@ private TupleDescriptor resolveColumnRef(TableName tblName, String colName) thro
for (TupleDescriptor desc : tupleByAlias.get(tblName.toString())) {
//result = desc;
if (!isVisible(desc.getId())) {
if (colName.equalsIgnoreCase(Column.DELETE_SIGN)) {
ErrorReport.reportAnalysisException(ErrorCode.ERR_UNIUQUE_KEY_USE_SEMI_JOIN,
Joiner.on(".").join(tblName.getTbl(),colName));
}
ErrorReport.reportAnalysisException(ErrorCode.ERR_ILLEGAL_COLUMN_REFERENCE_ERROR,
Joiner.on(".").join(tblName.getTbl(),colName));
}
Expand Down
4 changes: 4 additions & 0 deletions fe/fe-core/src/main/java/org/apache/doris/common/ErrorCode.java
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ public enum ErrorCode {
ERR_ILLEGAL_COLUMN_REFERENCE_ERROR(1053, new byte[] {'2', '3', '0', '0', '1'},
"Illegal column/field reference '%s' of semi-/anti-join"),
ERR_BAD_FIELD_ERROR(1054, new byte[] {'4', '2', 'S', '2', '2'}, "Unknown column '%s' in '%s'"),
ERR_UNIUQUE_KEY_USE_SEMI_JOIN(1055, new byte[] {'2', '3', '0', '0', '1'},
"%s is a hidden column to mark whether a row deleted when unique key existed, " +
"'__DORIS_DELETE_SIGN__ = 0' will appear in where clause, that will cause semi join syntax error, " +
"please use '[not] in/existed' as replacement."),
ERR_WRONG_VALUE_COUNT(1058, new byte[] {'2', '1', 'S', '0', '1'}, "Column count doesn't match value count"),
ERR_DUP_FIELDNAME(1060, new byte[] {'4', '2', 'S', '2', '1'}, "Duplicate column name '%s'"),
ERR_NONUNIQ_TABLE(1066, new byte[] {'4', '2', '0', '0', '0'}, "Not unique table/alias: '%s'"),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

package org.apache.doris.analysis;

import org.apache.doris.common.AnalysisException;
import org.apache.doris.qe.ConnectContext;
import org.apache.doris.utframe.DorisAssert;
import org.apache.doris.utframe.UtFrameUtils;
import org.junit.*;
import org.junit.rules.ExpectedException;

import java.util.UUID;

public class UniqueKeySemiJoinTest {
private static String runningDir = "fe/mocked/DemoTest/" + UUID.randomUUID().toString() + "/";
private static DorisAssert dorisAssert;

@Rule
public ExpectedException expectedEx = ExpectedException.none();

@AfterClass
public static void tearDown() throws Exception {
UtFrameUtils.cleanDorisFeDir(runningDir);
}

@BeforeClass
public static void setUp() throws Exception {
UtFrameUtils.createMinDorisCluster(runningDir);
String createTbl1Str = "CREATE TABLE `t0` (\n" +
" `c0` tinyint NOT NULL,\n" +
" `c1` tinyint NOT NULL\n" +
") ENGINE=OLAP\n" +
"UNIQUE KEY(`c0`)\n" +
"COMMENT \"OLAP\"\n" +
"DISTRIBUTED BY HASH(`c0`) BUCKETS 10\n" +
"PROPERTIES (\n" +
"\"replication_num\" = \"1\",\n" +
"\"in_memory\" = \"false\",\n" +
"\"storage_format\" = \"DEFAULT\"\n" +
");";
String createTbl2Str = "CREATE TABLE `t1` (\n" +
" `c0` tinyint NOT NULL,\n" +
" `c1` tinyint NOT NULL\n" +
") ENGINE=OLAP\n" +
"UNIQUE KEY(`c0`)\n" +
"COMMENT \"OLAP\"\n" +
"DISTRIBUTED BY HASH(`c0`) BUCKETS 10\n" +
"PROPERTIES (\n" +
"\"replication_num\" = \"1\",\n" +
"\"in_memory\" = \"false\",\n" +
"\"storage_format\" = \"DEFAULT\"\n" +
");";
dorisAssert = new DorisAssert();
dorisAssert.withDatabase("db1").useDatabase("db1");
dorisAssert.withTable(createTbl1Str)
.withTable(createTbl2Str);
}

@Test
public void testSemiJoin() throws Exception {
String sql = " SELECT * FROM t1 LEFT SEMI JOIN t0 ON t1.c0 = t0.c0";
try {
dorisAssert.query(sql).explainQuery();
Assert.fail("t0.__DORIS_DELETE_SIGN__ is a hidden column to mark whether a row deleted when unique key existed, '__DORIS_DELETE_SIGN__ = 0' will appear in where clause, that will cause semi join syntax error, please use not in/existed as replacement.");
} catch (AnalysisException e) {
System.out.println(e.getMessage());
}

sql = " SELECT * FROM t1 RIGHT SEMI JOIN t0 ON t1.c0 = t0.c0";
try {
dorisAssert.query(sql).explainQuery();
Assert.fail("t0.__DORIS_DELETE_SIGN__ is a hidden column to mark whether a row deleted when unique key existed, '__DORIS_DELETE_SIGN__ = 0' will appear in where clause, that will cause semi join syntax error, please use not in/existed as replacement.");
} catch (AnalysisException e) {
System.out.println(e.getMessage());
}

sql = " SELECT * FROM t1 LEFT ANTI JOIN t0 ON t1.c0 = t0.c0";
try {
dorisAssert.query(sql).explainQuery();
Assert.fail("t0.__DORIS_DELETE_SIGN__ is a hidden column to mark whether a row deleted when unique key existed, '__DORIS_DELETE_SIGN__ = 0' will appear in where clause, that will cause semi join syntax error, please use not in/existed as replacement.");
} catch (AnalysisException e) {
System.out.println(e.getMessage());
}

sql = " SELECT * FROM t1 RIGHT ANTI JOIN t0 ON t1.c0 = t0.c0";
try {
dorisAssert.query(sql).explainQuery();
Assert.fail("t0.__DORIS_DELETE_SIGN__ is a hidden column to mark whether a row deleted when unique key existed, '__DORIS_DELETE_SIGN__ = 0' will appear in where clause, that will cause semi join syntax error, please use not in/existed as replacement.");
} catch (AnalysisException e) {
System.out.println(e.getMessage());
}

sql = " SELECT * FROM t1 LEFT JOIN t0 ON t1.c0 = t0.c0";
dorisAssert.query(sql).explainQuery();

sql = " SELECT * FROM t1 RIGHT JOIN t0 ON t1.c0 = t0.c0";
dorisAssert.query(sql).explainQuery();

sql = " SELECT * FROM t1 where c0 NOT IN ( select c0 from t0)";
dorisAssert.query(sql).explainQuery();
}
}