hive的表结构查询需要根据DESCRIBE FORMATTED %s.%s结果进行解析。

This commit is contained in:
tmlx1990
2024-03-14 18:17:51 +08:00
parent e29975b933
commit 7fb26381bd

View File

@ -7,19 +7,15 @@ import ai.chat2db.spi.CommandExecutor;
import ai.chat2db.spi.MetaData;
import ai.chat2db.spi.SqlBuilder;
import ai.chat2db.spi.jdbc.DefaultMetaService;
import ai.chat2db.spi.model.Database;
import ai.chat2db.spi.model.Schema;
import ai.chat2db.spi.model.Table;
import ai.chat2db.spi.model.TableMeta;
import ai.chat2db.spi.model.*;
import ai.chat2db.spi.sql.SQLExecutor;
import jakarta.validation.constraints.NotEmpty;
import org.apache.commons.lang3.StringUtils;
import java.io.Reader;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;
public class HiveMetaData extends DefaultMetaService implements MetaData {
@ -97,28 +93,179 @@ public class HiveMetaData extends DefaultMetaService implements MetaData {
}
private static String SELECT_TABLE_SQL = "DESCRIBE EXTENDED %s";
private static String SELECT_TAB_COLS = "DESCRIBE FORMATTED `%s`.`%s`";
// TODO 待完善
@Override
public List<Table> tables(Connection connection, String databaseName, String schemaName, String tableName) {
String sql = String.format(SELECT_TABLE_SQL, schemaName);
if (StringUtils.isNotBlank(tableName)) {
sql = sql + " and A.TABLE_NAME = '" + tableName + "'";
}
public List<TableColumn> columns(Connection connection, String databaseName, String schemaName, String tableName) {
String sql = String.format(SELECT_TAB_COLS, databaseName, tableName);
return SQLExecutor.getInstance().execute(connection, sql, resultSet -> {
List<Table> tables = new ArrayList<>();
List<TableColumn> tableColumns = new ArrayList<>();
Map<String, String> detailTableInfo = new HashMap<>();
Map<String, String> tableParams = new HashMap<>();
Map<String, String> storageInfo = new HashMap<>();
Map<String, String> storageDescParams = new HashMap<>();
Map<String, Map<String, String>> constraints = new HashMap<>();
List<Map<String, String>> columns = new ArrayList<>();
List<Map<String, String>> partitions = new ArrayList<>();
Map<String, String> moduleMap = getDescTableModule();
String infoModule = "";
while (resultSet.next()) {
Table table = new Table();
table.setDatabaseName(databaseName);
table.setSchemaName(schemaName);
table.setName(resultSet.getString("TABLE_NAME"));
table.setComment(resultSet.getString("COMMENTS"));
tables.add(table);
String title = resultSet.getString(1).trim();
if (("".equals(title) && resultSet.getString(2) == null) || "# Constraints".equals(title)) {
continue;
}
if (moduleMap.containsKey(title)) {
if ("partition_info".equals(infoModule) && "col_name".equals(moduleMap.get(title))) {
continue;
}
infoModule = moduleMap.get(title);
continue;
}
String key = null;
String value = null;
switch (infoModule) {
case "col_name":
Map<String, String> map = new HashMap<>();
int colNum = resultSet.getMetaData().getColumnCount();
for (int col = 1; col <= colNum; col++) {
String columnName = resultSet.getMetaData().getColumnName(col);
String columnValue = resultSet.getString(columnName);
map.put(columnName, columnValue);
}
columns.add(map);
break;
case "table_info":
key = resultSet.getString(1).trim().replace(":", "");
value = resultSet.getString(2).trim();
detailTableInfo.put(key, value);
break;
case "table_param":
key = resultSet.getString(2).trim().replace(":", "");
value = resultSet.getString(3).trim();
tableParams.put(key, value);
break;
case "storage_info":
key = resultSet.getString(1).trim().replace(":", "");
value = resultSet.getString(2).trim();
storageInfo.put(key, value);
break;
case "storage_desc":
key = resultSet.getString(2).trim().replace(":", "");
value = resultSet.getString(3).trim();
storageDescParams.put(key, value);
break;
case "primary_key":
Map<String, String> primaryKeyMap = constraints.getOrDefault("primaryKey", new HashMap<>());
if ("Table:".equals(title.trim())) {
resultSet.next();
}
String primaryKeyName = resultSet.getString(2).trim();
resultSet.next();
key = resultSet.getString(2).trim();
primaryKeyMap.put(key, primaryKeyName);
constraints.put("primaryKey", primaryKeyMap);
break;
case "not_null_constraint":
Map<String, String> notNullMap = constraints.getOrDefault("notnull", new HashMap<>());
if ("Table:".equals(title.trim())) {
resultSet.next();
}
String notNullConstraintName = resultSet.getString(2).trim();
resultSet.next();
key = resultSet.getString(2).trim();
notNullMap.put(key, notNullConstraintName);
constraints.put("notnull", notNullMap);
break;
case "default_constraint":
Map<String, String> defaultMap = constraints.getOrDefault("default", new HashMap<>());
if ("Table:".equals(title.trim())) { resultSet.next();}
String defaultConstraintName = resultSet.getString(2).trim();
resultSet.next();
key = resultSet.getString(1).trim().split(":")[1];
value = resultSet.getString(2).trim();
int valueIndex = value.indexOf(":");
value = value.substring(valueIndex + 1);
defaultMap.put(key + "_constraintName", defaultConstraintName);
constraints.put("default", defaultMap);
break;
case "partition_info":
Map<String, String> partitionMap = new HashMap<>();
int partitionColNum = resultSet.getMetaData().getColumnCount();
for (int col = 0; col < partitionColNum; col++) {
String columnName = resultSet.getMetaData().getColumnName(col + 1);
String columnValue = resultSet.getString(columnName);
partitionMap.put(columnName, columnValue);
}
partitions.add(partitionMap);
break;
default:
System.out.print("unknown module,please update method to support it : " + infoModule);
}
}
return tables;
TableColumn tableColumn = new TableColumn();
tableColumn.setTableName(tableName);
tableColumn.setSchemaName(schemaName);
tableColumn.setName(resultSet.getString("col_name"));
tableColumn.setColumnType(resultSet.getString("data_type"));
/*Integer dataPrecision = resultSet.getInt("DATA_PRECISION");
if(dataPrecision!=null) {
tableColumn.setColumnSize(dataPrecision);
}else {
tableColumn.setColumnSize(resultSet.getInt("DATA_LENGTH"));
}*/
tableColumn.setComment(resultSet.getString("comment"));
/* tableColumn.setNullable("Y".equalsIgnoreCase(resultSet.getString("NULLABLE")) ? 1 : 0);
tableColumn.setOrdinalPosition(resultSet.getInt("COLUMN_ID"));
tableColumn.setDecimalDigits(resultSet.getInt("DATA_SCALE"));
String charUsed = resultSet.getString("CHAR_USED");
if ("B".equalsIgnoreCase(charUsed)) {
tableColumn.setUnit("BYTE");
} else if ("C".equalsIgnoreCase(charUsed)) {
tableColumn.setUnit("CHAR");
}*/
tableColumns.add(tableColumn);
return tableColumns;
});
}
private static Map<String, String> getDescTableModule() {
Map<String, String> descTableModule = new HashMap<>();
descTableModule.put("# col_name", "col_name");
descTableModule.put("# Detailed Table Information", "table_info");
descTableModule.put("Table Parameters:", "table_param");
descTableModule.put("# Storage Information", "storage_info");
descTableModule.put("Storage Desc Params:", "storage_desc");
descTableModule.put("# Not Null Constraints", "not_null_constraint");
descTableModule.put("# Default Constraints", "default_constraint");
descTableModule.put("# Partition Information", "partition_info");
descTableModule.put("# Primary Key", "primary_key");
return descTableModule;
}
public static String format(String name) {
return "`" + name + "`";
}