in src/main/user-impl/java/com/mysql/cj/jdbc/DatabaseMetaDataMysqlSchema.java [1423:1571]
public ResultSet getColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) throws SQLException {
final String columnNameFilter = normalizeIdentifierQuoting(columnNamePattern);
final List<Row> rows = new ArrayList<>();
try (final Statement stmt = getJdbcConnection().getMetaDataSafeStatement()) {
SortedMap<String, List<String>> tableNamesPerDb = new TreeMap<>();
ResultSet tables = null;
try {
tables = getTables(catalog, schemaPattern, tableNamePattern, null);
while (tables.next()) {
final String db = tables.getString(chooseBasedOnDatabaseTerm(() -> "TABLE_CAT", () -> "TABLE_SCHEM"));
List<String> tableNames = tableNamesPerDb.get(db);
if (tableNames == null) {
tableNames = new ArrayList<>();
}
tableNames.add(tables.getString("TABLE_NAME"));
tableNamesPerDb.put(db, tableNames);
}
} finally {
if (tables != null) {
try {
tables.close();
} catch (Exception sqlEx) {
AssertionFailedException.shouldNotHappen(sqlEx);
}
tables = null;
}
}
for (String dbName : tableNamesPerDb.keySet()) {
for (String tableName : tableNamesPerDb.get(dbName)) {
ResultSet rs = null;
try {
StringBuilder query = new StringBuilder("SHOW FULL COLUMNS FROM ");
query.append(StringUtils.quoteIdentifier(tableName, getQuoteId(), true));
query.append(" FROM ");
query.append(StringUtils.quoteIdentifier(dbName, getQuoteId(), true));
// Find column ordinals if column name pattern is not '%'.
// SHOW COLUMNS does not include ordinal information so another round trip is required to return all columns in the table and compute
// their ordinal positions.
boolean fixUpOrdinalsRequired = false;
Map<String, Integer> ordinalFixUpMap = null;
if (columnNameFilter != null && !columnNameFilter.equals("%")) {
fixUpOrdinalsRequired = true;
ordinalFixUpMap = new HashMap<>();
rs = stmt.executeQuery(query.toString());
int ordinalPos = 1;
while (rs.next()) {
String columnName = rs.getString("Field");
ordinalFixUpMap.put(columnName, ordinalPos++);
}
rs.close();
}
if (columnNameFilter != null) {
query.append(" LIKE ");
query.append(StringUtils.quoteIdentifier(columnNameFilter, "'", true));
}
rs = stmt.executeQuery(query.toString());
int ordPos = 1;
while (rs.next()) {
TypeDescriptor typeDesc = new TypeDescriptor(rs.getString("Type"), rs.getString("Null"));
byte[][] row = new byte[24][];
row[0] = chooseBasedOnDatabaseTerm(() -> s2b(dbName), () -> s2b("def")); // TABLE_CAT
row[1] = chooseBasedOnDatabaseTerm(() -> null, () -> s2b(dbName)); // TABLE_SCHEM
row[2] = s2b(tableName); // TABLE_NAME
row[3] = rs.getBytes("Field"); // COLUMN_NAME
row[4] = n2b(typeDesc.getJdbcType()); // DATA_TYPE
row[5] = s2b(typeDesc.mysqlType.getName()); // TYPE_NAME
if (typeDesc.columnSize == null) {
row[6] = null; // COLUMN_SIZE
} else {
String collation = rs.getString("Collation");
int mbminlen = 1;
if (collation != null) {
// Not null collation could only be returned by server for character types, so no need to check type name.
if (collation.indexOf("ucs2") > -1 || collation.indexOf("utf16") > -1) {
mbminlen = 2;
} else if (collation.indexOf("utf32") > -1) {
mbminlen = 4;
}
}
row[6] = mbminlen == 1 ? n2b(typeDesc.columnSize) : n2b(typeDesc.columnSize / mbminlen); // COLUMN_SIZE
}
row[7] = n2b(typeDesc.bufferLength); // BUFFER_LENGTH
row[8] = typeDesc.decimalDigits == null ? null : n2b(typeDesc.decimalDigits); // DECIMAL_DIGITS
row[9] = n2b(typeDesc.numPrecRadix); // NUM_PREC_RADIX
row[10] = n2b(typeDesc.nullability); // NULLABLE
row[11] = rs.getBytes("Comment"); // REMARKS
row[12] = rs.getBytes("Default"); // COLUMN_DEF
row[13] = new byte[] { (byte) '0' }; // SQL_DATA_TYPE
row[14] = new byte[] { (byte) '0' }; // SQL_DATETIME_SUB
if (StringUtils.indexOfIgnoreCase(typeDesc.mysqlType.getName(), "CHAR") != -1
|| StringUtils.indexOfIgnoreCase(typeDesc.mysqlType.getName(), "BLOB") != -1
|| StringUtils.indexOfIgnoreCase(typeDesc.mysqlType.getName(), "TEXT") != -1
|| StringUtils.indexOfIgnoreCase(typeDesc.mysqlType.getName(), "ENUM") != -1
|| StringUtils.indexOfIgnoreCase(typeDesc.mysqlType.getName(), "SET") != -1
|| StringUtils.indexOfIgnoreCase(typeDesc.mysqlType.getName(), "BINARY") != -1) {
row[15] = row[6]; // CHAR_OCTET_LENGTH
} else {
row[15] = null; // CHAR_OCTET_LENGTH
}
if (!fixUpOrdinalsRequired) {
row[16] = n2b(ordPos++); // ORDINAL_POSITION
} else {
String origColName = rs.getString("Field");
Integer realOrdinal = ordinalFixUpMap.get(origColName);
if (realOrdinal != null) {
row[16] = n2b(realOrdinal); // ORDINAL_POSITION
} else {
throw SQLError.createSQLException(Messages.getString("DatabaseMetaData.10"), MysqlErrorNumbers.SQLSTATE_CONNJ_GENERAL_ERROR,
getExceptionInterceptor());
}
}
row[17] = s2b(typeDesc.isNullable); // IS_NULLABLE
row[18] = null; // SCOPE_CATALOG
row[19] = null; // SCOPE_SCHEMA
row[20] = null; // SCOPE_TABLE
row[21] = null; // SOURCE_DATA_TYPE
String extra = rs.getString("Extra");
if (extra != null) {
row[22] = s2b(StringUtils.indexOfIgnoreCase(extra, "auto_increment") != -1 ? "YES" : "NO"); // IS_AUTOINCREMENT
row[23] = s2b(StringUtils.indexOfIgnoreCase(extra, "generated") != -1 ? "YES" : "NO"); // IS_GENERATEDCOLUMN
} else {
row[22] = s2b(""); // IS_AUTOINCREMENT
row[23] = s2b(""); // IS_GENERATEDCOLUMN
}
rows.add(new ByteArrayRow(row, getExceptionInterceptor()));
}
} finally {
if (rs != null) {
try {
rs.close();
} catch (Exception e) {
}
rs = null;
}
}
}
}
}
return getResultSetFactory().createFromResultsetRows(ResultSet.CONCUR_READ_ONLY, ResultSet.TYPE_SCROLL_INSENSITIVE,
new ResultsetRowsStatic(rows, new DefaultColumnDefinition(createColumnsFields())));
}