0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019 package org.apache.hive.service.cli.operation;
0020
0021 import java.sql.DatabaseMetaData;
0022 import java.util.ArrayList;
0023 import java.util.Collections;
0024 import java.util.HashMap;
0025 import java.util.HashSet;
0026 import java.util.List;
0027 import java.util.Map;
0028 import java.util.Map.Entry;
0029 import java.util.Set;
0030 import java.util.regex.Pattern;
0031
0032 import org.apache.hadoop.hive.conf.HiveConf.ConfVars;
0033 import org.apache.hadoop.hive.metastore.IMetaStoreClient;
0034 import org.apache.hadoop.hive.metastore.api.PrimaryKeysRequest;
0035 import org.apache.hadoop.hive.metastore.api.SQLPrimaryKey;
0036 import org.apache.hadoop.hive.metastore.api.Table;
0037 import org.apache.hadoop.hive.ql.metadata.TableIterable;
0038 import org.apache.hadoop.hive.ql.security.authorization.plugin.HiveOperationType;
0039 import org.apache.hadoop.hive.ql.security.authorization.plugin.HivePrivilegeObject;
0040 import org.apache.hadoop.hive.ql.security.authorization.plugin.HivePrivilegeObject.HivePrivilegeObjectType;
0041 import org.apache.hadoop.hive.ql.session.SessionState;
0042 import org.apache.hadoop.hive.serde2.thrift.Type;
0043 import org.apache.hive.service.cli.ColumnDescriptor;
0044 import org.apache.hive.service.cli.FetchOrientation;
0045 import org.apache.hive.service.cli.HiveSQLException;
0046 import org.apache.hive.service.cli.OperationState;
0047 import org.apache.hive.service.cli.OperationType;
0048 import org.apache.hive.service.cli.RowSet;
0049 import org.apache.hive.service.cli.RowSetFactory;
0050 import org.apache.hive.service.cli.TableSchema;
0051 import org.apache.hive.service.cli.session.HiveSession;
0052
0053
0054
0055
0056
0057 public class GetColumnsOperation extends MetadataOperation {
0058
0059 protected static final TableSchema RESULT_SET_SCHEMA = new TableSchema()
0060 .addPrimitiveColumn("TABLE_CAT", Type.STRING_TYPE,
0061 "Catalog name. NULL if not applicable")
0062 .addPrimitiveColumn("TABLE_SCHEM", Type.STRING_TYPE,
0063 "Schema name")
0064 .addPrimitiveColumn("TABLE_NAME", Type.STRING_TYPE,
0065 "Table name")
0066 .addPrimitiveColumn("COLUMN_NAME", Type.STRING_TYPE,
0067 "Column name")
0068 .addPrimitiveColumn("DATA_TYPE", Type.INT_TYPE,
0069 "SQL type from java.sql.Types")
0070 .addPrimitiveColumn("TYPE_NAME", Type.STRING_TYPE,
0071 "Data source dependent type name, for a UDT the type name is fully qualified")
0072 .addPrimitiveColumn("COLUMN_SIZE", Type.INT_TYPE,
0073 "Column size. For char or date types this is the maximum number of characters,"
0074 + " for numeric or decimal types this is precision.")
0075 .addPrimitiveColumn("BUFFER_LENGTH", Type.TINYINT_TYPE,
0076 "Unused")
0077 .addPrimitiveColumn("DECIMAL_DIGITS", Type.INT_TYPE,
0078 "The number of fractional digits")
0079 .addPrimitiveColumn("NUM_PREC_RADIX", Type.INT_TYPE,
0080 "Radix (typically either 10 or 2)")
0081 .addPrimitiveColumn("NULLABLE", Type.INT_TYPE,
0082 "Is NULL allowed")
0083 .addPrimitiveColumn("REMARKS", Type.STRING_TYPE,
0084 "Comment describing column (may be null)")
0085 .addPrimitiveColumn("COLUMN_DEF", Type.STRING_TYPE,
0086 "Default value (may be null)")
0087 .addPrimitiveColumn("SQL_DATA_TYPE", Type.INT_TYPE,
0088 "Unused")
0089 .addPrimitiveColumn("SQL_DATETIME_SUB", Type.INT_TYPE,
0090 "Unused")
0091 .addPrimitiveColumn("CHAR_OCTET_LENGTH", Type.INT_TYPE,
0092 "For char types the maximum number of bytes in the column")
0093 .addPrimitiveColumn("ORDINAL_POSITION", Type.INT_TYPE,
0094 "Index of column in table (starting at 1)")
0095 .addPrimitiveColumn("IS_NULLABLE", Type.STRING_TYPE,
0096 "\"NO\" means column definitely does not allow NULL values; "
0097 + "\"YES\" means the column might allow NULL values. An empty "
0098 + "string means nobody knows.")
0099 .addPrimitiveColumn("SCOPE_CATALOG", Type.STRING_TYPE,
0100 "Catalog of table that is the scope of a reference attribute "
0101 + "(null if DATA_TYPE isn't REF)")
0102 .addPrimitiveColumn("SCOPE_SCHEMA", Type.STRING_TYPE,
0103 "Schema of table that is the scope of a reference attribute "
0104 + "(null if the DATA_TYPE isn't REF)")
0105 .addPrimitiveColumn("SCOPE_TABLE", Type.STRING_TYPE,
0106 "Table name that this the scope of a reference attribure "
0107 + "(null if the DATA_TYPE isn't REF)")
0108 .addPrimitiveColumn("SOURCE_DATA_TYPE", Type.SMALLINT_TYPE,
0109 "Source type of a distinct type or user-generated Ref type, "
0110 + "SQL type from java.sql.Types (null if DATA_TYPE isn't DISTINCT or user-generated REF)")
0111 .addPrimitiveColumn("IS_AUTO_INCREMENT", Type.STRING_TYPE,
0112 "Indicates whether this column is auto incremented.");
0113
0114 private final String catalogName;
0115 private final String schemaName;
0116 private final String tableName;
0117 private final String columnName;
0118
0119 protected final RowSet rowSet;
0120
0121 protected GetColumnsOperation(HiveSession parentSession, String catalogName, String schemaName,
0122 String tableName, String columnName) {
0123 super(parentSession, OperationType.GET_COLUMNS);
0124 this.catalogName = catalogName;
0125 this.schemaName = schemaName;
0126 this.tableName = tableName;
0127 this.columnName = columnName;
0128 this.rowSet = RowSetFactory.create(RESULT_SET_SCHEMA, getProtocolVersion(), false);
0129 }
0130
0131 @Override
0132 public void runInternal() throws HiveSQLException {
0133 setState(OperationState.RUNNING);
0134 try {
0135 IMetaStoreClient metastoreClient = getParentSession().getMetaStoreClient();
0136 String schemaPattern = convertSchemaPattern(schemaName);
0137 String tablePattern = convertIdentifierPattern(tableName, true);
0138
0139 Pattern columnPattern = null;
0140 if (columnName != null) {
0141 columnPattern = Pattern.compile(convertIdentifierPattern(columnName, false));
0142 }
0143
0144 List<String> dbNames = metastoreClient.getDatabases(schemaPattern);
0145 Collections.sort(dbNames);
0146 Map<String, List<String>> db2Tabs = new HashMap<>();
0147
0148 for (String dbName : dbNames) {
0149 List<String> tableNames = metastoreClient.getTables(dbName, tablePattern);
0150 Collections.sort(tableNames);
0151 db2Tabs.put(dbName, tableNames);
0152 }
0153
0154 if (isAuthV2Enabled()) {
0155 List<HivePrivilegeObject> privObjs = getPrivObjs(db2Tabs);
0156 String cmdStr = "catalog : " + catalogName + ", schemaPattern : " + schemaName
0157 + ", tablePattern : " + tableName;
0158 authorizeMetaGets(HiveOperationType.GET_COLUMNS, privObjs, cmdStr);
0159 }
0160
0161 int maxBatchSize = SessionState.get().getConf().getIntVar(ConfVars.METASTORE_BATCH_RETRIEVE_MAX);
0162 for (Entry<String, List<String>> dbTabs : db2Tabs.entrySet()) {
0163 String dbName = dbTabs.getKey();
0164 List<String> tableNames = dbTabs.getValue();
0165
0166 for (Table table : new TableIterable(metastoreClient, dbName, tableNames, maxBatchSize)) {
0167
0168 TableSchema schema = new TableSchema(metastoreClient.getSchema(dbName,
0169 table.getTableName()));
0170 List<SQLPrimaryKey> primaryKeys = metastoreClient.getPrimaryKeys(new PrimaryKeysRequest(dbName, table.getTableName()));
0171 Set<String> pkColNames = new HashSet<>();
0172 for(SQLPrimaryKey key : primaryKeys) {
0173 pkColNames.add(key.getColumn_name().toLowerCase());
0174 }
0175 for (ColumnDescriptor column : schema.getColumnDescriptors()) {
0176 if (columnPattern != null && !columnPattern.matcher(column.getName()).matches()) {
0177 continue;
0178 }
0179 Object[] rowData = new Object[] {
0180 null,
0181 table.getDbName(),
0182 table.getTableName(),
0183 column.getName(),
0184 column.getType().toJavaSQLType(),
0185 column.getTypeName(),
0186 column.getTypeDescriptor().getColumnSize(),
0187 null,
0188 column.getTypeDescriptor().getDecimalDigits(),
0189 column.getType().getNumPrecRadix(),
0190 pkColNames.contains(column.getName().toLowerCase()) ? DatabaseMetaData.columnNoNulls
0191 : DatabaseMetaData.columnNullable,
0192 column.getComment(),
0193 null,
0194 null,
0195 null,
0196 null,
0197 column.getOrdinalPosition(),
0198 pkColNames.contains(column.getName().toLowerCase()) ? "NO" : "YES",
0199 null,
0200 null,
0201 null,
0202 null,
0203 "NO",
0204 };
0205 rowSet.addRow(rowData);
0206 }
0207 }
0208 }
0209 setState(OperationState.FINISHED);
0210 } catch (Exception e) {
0211 setState(OperationState.ERROR);
0212 throw new HiveSQLException(e);
0213 }
0214
0215 }
0216
0217
0218 private List<HivePrivilegeObject> getPrivObjs(Map<String, List<String>> db2Tabs) {
0219 List<HivePrivilegeObject> privObjs = new ArrayList<>();
0220 for (Entry<String, List<String>> dbTabs : db2Tabs.entrySet()) {
0221 for (String tabName : dbTabs.getValue()) {
0222 privObjs.add(new HivePrivilegeObject(HivePrivilegeObjectType.TABLE_OR_VIEW, dbTabs.getKey(),
0223 tabName));
0224 }
0225 }
0226 return privObjs;
0227 }
0228
0229
0230
0231
0232 @Override
0233 public TableSchema getResultSetSchema() throws HiveSQLException {
0234 assertState(OperationState.FINISHED);
0235 return RESULT_SET_SCHEMA;
0236 }
0237
0238
0239
0240
0241 @Override
0242 public RowSet getNextRowSet(FetchOrientation orientation, long maxRows) throws HiveSQLException {
0243 assertState(OperationState.FINISHED);
0244 validateDefaultFetchOrientation(orientation);
0245 if (orientation.equals(FetchOrientation.FETCH_FIRST)) {
0246 rowSet.setStartOffset(0);
0247 }
0248 return rowSet.extractSubset((int)maxRows);
0249 }
0250
0251 }