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