TableIf.java
// 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.catalog;
import org.apache.doris.alter.AlterCancelException;
import org.apache.doris.cluster.ClusterNamespace;
import org.apache.doris.common.DdlException;
import org.apache.doris.common.MetaNotFoundException;
import org.apache.doris.common.Pair;
import org.apache.doris.datasource.systable.SysTable;
import org.apache.doris.statistics.AnalysisInfo;
import org.apache.doris.statistics.BaseAnalysisTask;
import org.apache.doris.statistics.ColumnStatistic;
import org.apache.doris.thrift.TTableDescriptor;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.DataOutput;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.TimeUnit;
public interface TableIf {
Logger LOG = LogManager.getLogger(TableIf.class);
long UNKNOWN_ROW_COUNT = -1;
default void readLock() {
}
default boolean tryReadLock(long timeout, TimeUnit unit) {
return true;
}
default void readUnlock() {
}
default void writeLock() {
}
default boolean writeLockIfExist() {
return true;
}
default boolean tryWriteLock(long timeout, TimeUnit unit) {
return true;
}
default void writeUnlock() {
}
default boolean isWriteLockHeldByCurrentThread() {
return true;
}
default <E extends Exception> void writeLockOrException(E e) throws E {
}
default void writeLockOrDdlException() throws DdlException {
}
default void writeLockOrMetaException() throws MetaNotFoundException {
}
default void writeLockOrAlterCancelException() throws AlterCancelException {
}
default boolean tryWriteLockOrMetaException(long timeout, TimeUnit unit) throws MetaNotFoundException {
return true;
}
default <E extends Exception> boolean tryWriteLockOrException(long timeout, TimeUnit unit, E e) throws E {
return true;
}
default boolean tryWriteLockIfExist(long timeout, TimeUnit unit) {
return true;
}
long getId();
String getName();
TableType getType();
List<Column> getFullSchema();
List<Column> getBaseSchema();
default Set<Column> getSchemaAllIndexes(boolean full) {
Set<Column> ret = Sets.newHashSet();
ret.addAll(getBaseSchema());
return ret;
}
default List<Column> getBaseSchemaOrEmpty() {
try {
return getBaseSchema();
} catch (Exception e) {
LOG.warn("failed to get base schema for table {}", getName(), e);
return Lists.newArrayList();
}
}
List<Column> getBaseSchema(boolean full);
void setNewFullSchema(List<Column> newSchema);
Column getColumn(String name);
default int getBaseColumnIdxByName(String colName) {
int i = 0;
for (Column col : getBaseSchema()) {
if (col.getName().equalsIgnoreCase(colName)) {
return i;
}
++i;
}
return -1;
}
String getMysqlType();
String getEngine();
String getComment();
long getCreateTime();
long getUpdateTime();
long getRowCount();
// Get the row count from cache,
// If miss, just return 0
// This is used for external table, because for external table, the fetching row count may be expensive
long getCachedRowCount();
long fetchRowCount();
long getDataLength();
long getAvgRowLength();
long getIndexLength();
long getLastCheckTime();
String getComment(boolean escapeQuota);
TTableDescriptor toThrift();
BaseAnalysisTask createAnalysisTask(AnalysisInfo info);
DatabaseIf getDatabase();
Optional<ColumnStatistic> getColumnStatistic(String colName);
/**
* @param columns Set of column names.
* @return Set of pairs. Each pair is <IndexName, ColumnName>. For external table, index name is table name.
*/
Set<Pair<String, String>> getColumnIndexPairs(Set<String> columns);
// Get all the chunk sizes of this table. Now, only HMS external table implemented this interface.
// For HMS external table, the return result is a list of all the files' size.
List<Long> getChunkSizes();
void write(DataOutput out) throws IOException;
/**
* return true if this kind of table need read lock when doing query plan.
*
* @return
*/
default boolean needReadLockWhenPlan() {
return false;
}
/**
* Doris table type.
*/
enum TableType {
MYSQL, ODBC, OLAP, SCHEMA, INLINE_VIEW, VIEW, BROKER, ELASTICSEARCH, HIVE,
@Deprecated
ICEBERG, @Deprecated
HUDI, JDBC,
TABLE_VALUED_FUNCTION, HMS_EXTERNAL_TABLE, ES_EXTERNAL_TABLE, MATERIALIZED_VIEW, JDBC_EXTERNAL_TABLE,
ICEBERG_EXTERNAL_TABLE, TEST_EXTERNAL_TABLE, PAIMON_EXTERNAL_TABLE, MAX_COMPUTE_EXTERNAL_TABLE,
HUDI_EXTERNAL_TABLE, TRINO_CONNECTOR_EXTERNAL_TABLE, LAKESOUl_EXTERNAL_TABLE, DICTIONARY, DORIS_EXTERNAL_TABLE;
public String toEngineName() {
switch (this) {
case MYSQL:
return "MySQL";
case ODBC:
return "Odbc";
case OLAP:
return "Doris";
case SCHEMA:
return "SYSTEM VIEW";
case INLINE_VIEW:
return "InlineView";
case VIEW:
return "View";
case BROKER:
return "Broker";
case ELASTICSEARCH:
return "ElasticSearch";
case HIVE:
return "Hive";
case HUDI:
case HUDI_EXTERNAL_TABLE:
return "Hudi";
case JDBC:
case JDBC_EXTERNAL_TABLE:
return "jdbc";
case TABLE_VALUED_FUNCTION:
return "Table_Valued_Function";
case HMS_EXTERNAL_TABLE:
return "hms";
case ES_EXTERNAL_TABLE:
return "es";
case ICEBERG:
case ICEBERG_EXTERNAL_TABLE:
return "iceberg";
case PAIMON_EXTERNAL_TABLE:
return "paimon";
case DICTIONARY:
return "dictionary";
case DORIS_EXTERNAL_TABLE:
return "External_Doris";
default:
return null;
}
}
public TableType getParentType() {
switch (this) {
case MATERIALIZED_VIEW:
return OLAP;
default:
return this;
}
}
// Refer to https://dev.mysql.com/doc/refman/8.0/en/information-schema-tables-table.html
public String toMysqlType() {
switch (this) {
case SCHEMA:
return "SYSTEM VIEW";
case INLINE_VIEW:
case VIEW:
return "VIEW";
case OLAP:
case MYSQL:
case ODBC:
case BROKER:
case ELASTICSEARCH:
case HIVE:
case HUDI:
case JDBC:
case JDBC_EXTERNAL_TABLE:
case TABLE_VALUED_FUNCTION:
case HMS_EXTERNAL_TABLE:
case ES_EXTERNAL_TABLE:
case ICEBERG_EXTERNAL_TABLE:
case PAIMON_EXTERNAL_TABLE:
case MATERIALIZED_VIEW:
case TRINO_CONNECTOR_EXTERNAL_TABLE:
case DORIS_EXTERNAL_TABLE:
return "BASE TABLE";
default:
return null;
}
}
}
default List<Column> getColumns() {
return Collections.emptyList();
}
default Set<String> getPartitionNames() {
return Collections.emptySet();
}
default Partition getPartition(String name) {
return null;
}
default List<String> getFullQualifiers() {
return ImmutableList.of(getDatabase().getCatalog().getName(),
ClusterNamespace.getNameFromFullName(getDatabase().getFullName()),
getName());
}
default String getNameWithFullQualifiers() {
DatabaseIf db = getDatabase();
// Some kind of table like FunctionGenTable does not belong to any database
if (db == null) {
return "null.null." + getName();
} else {
return db.getCatalog().getName()
+ "." + ClusterNamespace.getNameFromFullName(db.getFullName())
+ "." + getName();
}
}
default boolean isManagedTable() {
return getType() == TableType.OLAP || getType() == TableType.MATERIALIZED_VIEW;
}
default long getDataSize(boolean singleReplica) {
// TODO: Each tableIf should impl it by itself.
return 0;
}
default boolean isPartitionColumn(Column column) {
return false;
}
default Set<String> getDistributionColumnNames() {
return Sets.newHashSet();
}
default boolean isPartitionedTable() {
return false;
}
boolean autoAnalyzeEnabled();
TableIndexes getTableIndexes();
default boolean isTemporary() {
return false;
}
/**
* Get the map of supported system table types for this table.
* Key is the system table name (e.g., "snapshots", "partitions").
*
* @return map of system table name to SysTable
*/
default Map<String, SysTable> getSupportedSysTables() {
return Collections.emptyMap();
}
/**
* Find the SysTable that matches the given table name.
* Uses O(1) map lookup after extracting the system table name suffix.
*
* @param tableNameWithSysTableName e.g., "table$partitions"
* @return the matching SysTable, or empty if not found
*/
default Optional<SysTable> findSysTable(String tableNameWithSysTableName) {
String sysTableName = SysTable.getTableNameWithSysTableName(tableNameWithSysTableName).second;
if (sysTableName.isEmpty()) {
return Optional.empty();
}
return Optional.ofNullable(getSupportedSysTables().get(sysTableName));
}
}