Skip to content
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 @@ -46,7 +46,9 @@
import org.apache.doris.analysis.MultiPartitionDesc;
import org.apache.doris.analysis.PartitionDesc;
import org.apache.doris.analysis.PartitionKeyDesc;
import org.apache.doris.analysis.PartitionKeyDesc.PartitionKeyValueType;
import org.apache.doris.analysis.PartitionNames;
import org.apache.doris.analysis.PartitionValue;
import org.apache.doris.analysis.QueryStmt;
import org.apache.doris.analysis.RecoverDbStmt;
import org.apache.doris.analysis.RecoverPartitionStmt;
Expand Down Expand Up @@ -2251,6 +2253,8 @@ public void checkAvailableCapacity(Database db) throws DdlException {
db.checkQuota();
}

// below are private functions used by createOlapTable

private Type getChildTypeByName(String name, CreateTableStmt stmt)
throws AnalysisException {
List<Column> columns = stmt.getColumns();
Expand All @@ -2262,6 +2266,98 @@ private Type getChildTypeByName(String name, CreateTableStmt stmt)
throw new AnalysisException("Cannot find column `" + name + "` in table's columns");
}

private boolean findAllowNullforSlotRef(List<Column> baseSchema, SlotRef slot) throws AnalysisException {
for (Column col : baseSchema) {
if (col.nameEquals(slot.getColumnName(), true)) {
return col.isAllowNull();
}
}
throw new AnalysisException("Unknown partition column name:" + slot.getColumnName());
}

private void checkNullityEqual(ArrayList<Boolean> partitionSlotNullables, List<PartitionValue> item)
throws AnalysisException {
// for MAX_VALUE or somethings
if (item == null) {
return;
}
for (int i = 0; i < item.size(); i++) {
try {
if (!partitionSlotNullables.get(i) && item.get(i).isNullPartition()) {
throw new AnalysisException("Can't have null partition is for NOT NULL partition "
+ "column in partition expr's index " + i);
}
} catch (IndexOutOfBoundsException e) {
throw new AnalysisException("partition item's size out of partition columns: " + e.getMessage());
}
}
}

private void checkPartitionNullity(List<Column> baseSchema, PartitionDesc partitionDesc,
SinglePartitionDesc partition)
throws AnalysisException {
// in creating OlapTable, expr.desc is null. so we should find the column ourself.
ArrayList<Expr> partitionExprs = partitionDesc.getPartitionExprs();
ArrayList<Boolean> partitionSlotNullables = new ArrayList<Boolean>();
for (Expr expr : partitionExprs) {
if (expr instanceof SlotRef) {
partitionSlotNullables.add(findAllowNullforSlotRef(baseSchema, (SlotRef) expr));
} else if (expr instanceof FunctionCallExpr) {
partitionSlotNullables.add(Expr.isNullable(((FunctionCallExpr) expr).getFn(), expr.getChildren()));
} else {
throw new AnalysisException("Unknown partition expr type:" + expr.getExprName());
}
}

if (partition.getPartitionKeyDesc().getPartitionType() == PartitionKeyValueType.IN) {
List<List<PartitionValue>> inValues = partition.getPartitionKeyDesc().getInValues();
for (List<PartitionValue> item : inValues) {
checkNullityEqual(partitionSlotNullables, item);
}
} else if (partition.getPartitionKeyDesc().getPartitionType() == PartitionKeyValueType.LESS_THAN) {
// only upper
List<PartitionValue> upperValues = partition.getPartitionKeyDesc().getUpperValues();
checkNullityEqual(partitionSlotNullables, upperValues);
} else {
// fixed. upper and lower
List<PartitionValue> lowerValues = partition.getPartitionKeyDesc().getLowerValues();
List<PartitionValue> upperValues = partition.getPartitionKeyDesc().getUpperValues();
checkNullityEqual(partitionSlotNullables, lowerValues);
checkNullityEqual(partitionSlotNullables, upperValues);
}
}

private void checkLegalityofPartitionExprs(CreateTableStmt stmt, PartitionDesc partitionDesc)
throws AnalysisException {
for (Expr expr : partitionDesc.getPartitionExprs()) {
if (expr != null && expr instanceof FunctionCallExpr) { // test them
FunctionCallExpr func = (FunctionCallExpr) expr;
ArrayList<Expr> children = func.getChildren();
Type[] childTypes = new Type[children.size()];
for (int i = 0; i < children.size(); i++) {
if (children.get(i) instanceof LiteralExpr) {
childTypes[i] = children.get(i).getType();
} else if (children.get(i) instanceof SlotRef) {
childTypes[i] = getChildTypeByName(children.get(i).getExprName(), stmt);
} else {
throw new AnalysisException(String.format(
"partition expr %s has unrecognized parameter in slot %d", func.getExprName(), i));
}
}
Function fn = null;
try {
fn = func.getBuiltinFunction(func.getFnName().getFunction(), childTypes,
Function.CompareMode.IS_INDISTINGUISHABLE); // only for test
} catch (Exception e) {
throw new AnalysisException("partition expr " + func.getExprName() + " is illegal!");
}
if (fn == null) {
throw new AnalysisException("partition expr " + func.getExprName() + " is illegal!");
}
}
}
}

// Create olap table and related base index synchronously.
private boolean createOlapTable(Database db, CreateTableStmt stmt) throws UserException {
String tableName = stmt.getTableName();
Expand Down Expand Up @@ -2307,43 +2403,21 @@ private boolean createOlapTable(Database db, CreateTableStmt stmt) throws UserEx
// create partition info
PartitionDesc partitionDesc = stmt.getPartitionDesc();

// check legality of partiton exprs
ConnectContext ctx = ConnectContext.get();
Env env = Env.getCurrentEnv();

// check legality of partiton exprs.
if (ctx != null && env != null && partitionDesc != null && partitionDesc.getPartitionExprs() != null) {
for (Expr expr : partitionDesc.getPartitionExprs()) {
if (expr != null && expr instanceof FunctionCallExpr) { // test them
FunctionCallExpr func = (FunctionCallExpr) expr;
ArrayList<Expr> children = func.getChildren();
Type[] childTypes = new Type[children.size()];
for (int i = 0; i < children.size(); i++) {
if (children.get(i) instanceof LiteralExpr) {
childTypes[i] = children.get(i).getType();
} else if (children.get(i) instanceof SlotRef) {
childTypes[i] = getChildTypeByName(children.get(i).getExprName(), stmt);
} else {
throw new AnalysisException(String.format(
"partition expr %s has unrecognized parameter in slot %d", func.getExprName(), i));
}
}
Function fn = null;
try {
fn = func.getBuiltinFunction(func.getFnName().getFunction(), childTypes,
Function.CompareMode.IS_INDISTINGUISHABLE); // only for test
} catch (Exception e) {
throw new AnalysisException("partition expr " + func.getExprName() + " is illegal!");
}
if (fn == null) {
throw new AnalysisException("partition expr " + func.getExprName() + " is illegal!");
}
}
}
checkLegalityofPartitionExprs(stmt, partitionDesc);
}

PartitionInfo partitionInfo = null;
Map<String, Long> partitionNameToId = Maps.newHashMap();
if (partitionDesc != null) {
for (SinglePartitionDesc desc : partitionDesc.getSinglePartitionDescs()) {
// check legality of nullity of partition items.
checkPartitionNullity(baseSchema, partitionDesc, desc);

long partitionId = idGeneratorBuffer.getNextId();
partitionNameToId.put(desc.getPartitionName(), partitionId);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,8 @@ public void run(ConnectContext ctx, StmtExecutor executor) throws Exception {
LOG.debug("Nereids start to execute the create table command, query id: {}, tableName: {}",
ctx.queryId(), createTableInfo.getTableName());
}
try {
Env.getCurrentEnv().createTable(createTableStmt);
} catch (Exception e) {
throw new AnalysisException(e.getMessage(), e.getCause());
}

Env.getCurrentEnv().createTable(createTableStmt);
return;
}
LogicalPlan query = ctasQuery.get();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -372,17 +372,16 @@ public void testAbnormal() throws DdlException, ConfigException {

// single partition column with multi keys
ExceptionChecker
.expectThrowsWithMsg(IllegalArgumentException.class, "partition key desc list size[2] is not equal to partition column size[1]",
() -> createTable("create table test.tbl10\n"
+ "(k1 int not null, k2 varchar(128), k3 int, v1 int, v2 int)\n"
+ "partition by list(k1)\n"
+ "(\n"
+ "partition p1 values in (\"1\", \"3\", \"5\"),\n"
+ "partition p2 values in (\"2\", \"4\", \"6\"),\n"
+ "partition p3 values in ((\"7\", \"8\"))\n"
+ ")\n"
+ "distributed by hash(k2) buckets 1\n"
+ "properties('replication_num' = '1');"));
.expectThrowsWithMsg(AnalysisException.class,
"partition item's size out of partition columns: Index 1 out of bounds for length 1",
() -> createTable("create table test.tbl10\n"
+ "(k1 int not null, k2 varchar(128), k3 int, v1 int, v2 int)\n"
+ "partition by list(k1)\n" + "(\n"
+ "partition p1 values in (\"1\", \"3\", \"5\"),\n"
+ "partition p2 values in (\"2\", \"4\", \"6\"),\n"
+ "partition p3 values in ((\"7\", \"8\"))\n" + ")\n"
+ "distributed by hash(k2) buckets 1\n"
+ "properties('replication_num' = '1');"));

// multi partition columns with single key
ExceptionChecker
Expand All @@ -399,7 +398,7 @@ public void testAbnormal() throws DdlException, ConfigException {

// multi partition columns with multi keys
ExceptionChecker
.expectThrowsWithMsg(IllegalArgumentException.class, "partition key desc list size[3] is not equal to partition column size[2]",
.expectThrowsWithMsg(AnalysisException.class, "partition item's size out of partition columns: Index 2 out of bounds for length 2",
() -> createTable("create table test.tbl12\n"
+ "(k1 int not null, k2 varchar(128) not null, k3 int, v1 int, v2 int)\n"
+ "partition by list(k1, k2)\n"
Expand Down Expand Up @@ -922,8 +921,8 @@ public void testCreateTableWithMinLoadReplicaNum() throws Exception {

@Test
public void testCreateTableWithNerieds() throws Exception {
ExceptionChecker.expectThrowsWithMsg(org.apache.doris.nereids.exceptions.AnalysisException.class,
"Failed to check min load replica num",
ExceptionChecker.expectThrowsWithMsg(org.apache.doris.common.DdlException.class,
"Failed to check min load replica num",
() -> createTable("create table test.tbl_min_load_replica_num_2_nereids\n"
+ "(k1 int, k2 int)\n"
+ "duplicate key(k1)\n"
Expand Down Expand Up @@ -964,7 +963,7 @@ public void testCreateTableWithNerieds() throws Exception {
+ "distributed by hash(k1) buckets 10", true));

createDatabaseWithSql("create database db2 properties('replication_num' = '4')");
ExceptionChecker.expectThrowsWithMsg(org.apache.doris.nereids.exceptions.AnalysisException.class,
ExceptionChecker.expectThrowsWithMsg(DdlException.class,
"replication num should be less than the number of available backends. "
+ "replication num is 4, available backend num is 3",
() -> createTable("create table db2.tbl_4_replica\n"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ public void testCreateAndDropWithSql() throws Exception {
+ "PROPERTIES (\n"
+ " 'location'='hdfs://loc/db/tbl',\n"
+ " 'file_format'='orc')";
ExceptionChecker.expectThrowsWithMsg(org.apache.doris.nereids.exceptions.AnalysisException.class,
ExceptionChecker.expectThrowsWithMsg(org.apache.doris.common.UserException.class,
"errCode = 2, detailMessage = errCode = 2,"
+ " detailMessage = Create hive bucket table need set enable_create_hive_bucket_table to true",
() -> createTable(createBucketedTableErr, true));
Expand Down
Loading