in src/main/user-impl/java/com/mysql/cj/jdbc/DatabaseMetaDataUsingInfoSchema.java [645:795]
public ResultSet getProcedureColumns(String catalog, String schemaPattern, String procedureNamePattern, String columnNamePattern) throws SQLException {
String db = getDatabase(catalog, schemaPattern);
db = this.pedantic ? db : StringUtils.unQuoteIdentifier(db, this.quotedId);
boolean supportsFractSeconds = this.conn.getServerVersion().meetsMinimum(ServerVersion.parseVersion("5.6.4"));
StringBuilder sqlBuf = new StringBuilder(
this.databaseTerm.getValue() == DatabaseTerm.SCHEMA ? "SELECT SPECIFIC_CATALOG AS PROCEDURE_CAT, SPECIFIC_SCHEMA AS `PROCEDURE_SCHEM`,"
: "SELECT SPECIFIC_SCHEMA AS PROCEDURE_CAT, NULL AS `PROCEDURE_SCHEM`,");
sqlBuf.append(" SPECIFIC_NAME AS `PROCEDURE_NAME`, IFNULL(PARAMETER_NAME, '') AS `COLUMN_NAME`,");
sqlBuf.append(" CASE WHEN PARAMETER_MODE = 'IN' THEN ");
sqlBuf.append(procedureColumnIn);
sqlBuf.append(" WHEN PARAMETER_MODE = 'OUT' THEN ");
sqlBuf.append(procedureColumnOut);
sqlBuf.append(" WHEN PARAMETER_MODE = 'INOUT' THEN ");
sqlBuf.append(procedureColumnInOut);
sqlBuf.append(" WHEN ORDINAL_POSITION = 0 THEN ");
sqlBuf.append(procedureColumnReturn);
sqlBuf.append(" ELSE ");
sqlBuf.append(procedureColumnUnknown);
sqlBuf.append(" END AS `COLUMN_TYPE`, ");
appendJdbcTypeMappingQuery(sqlBuf, "DATA_TYPE", "DTD_IDENTIFIER");
sqlBuf.append(" AS `DATA_TYPE`, ");
sqlBuf.append("UPPER(CASE");
if (this.tinyInt1isBit) {
sqlBuf.append(" WHEN UPPER(DATA_TYPE)='TINYINT' THEN CASE");
sqlBuf.append(
" WHEN LOCATE('ZEROFILL', UPPER(DTD_IDENTIFIER)) = 0 AND LOCATE('UNSIGNED', UPPER(DTD_IDENTIFIER)) = 0 AND LOCATE('(1)', DTD_IDENTIFIER) != 0 THEN ");
sqlBuf.append(this.transformedBitIsBoolean ? "'BOOLEAN'" : "'BIT'");
sqlBuf.append(" WHEN LOCATE('UNSIGNED', UPPER(DTD_IDENTIFIER)) != 0 AND LOCATE('UNSIGNED', UPPER(DATA_TYPE)) = 0 THEN 'TINYINT UNSIGNED'");
sqlBuf.append(" ELSE DATA_TYPE END ");
}
sqlBuf.append(
" WHEN LOCATE('UNSIGNED', UPPER(DTD_IDENTIFIER)) != 0 AND LOCATE('UNSIGNED', UPPER(DATA_TYPE)) = 0 AND LOCATE('SET', UPPER(DATA_TYPE)) <> 1 AND LOCATE('ENUM', UPPER(DATA_TYPE)) <> 1 THEN CONCAT(DATA_TYPE, ' UNSIGNED')");
// spatial data types
sqlBuf.append(" WHEN UPPER(DATA_TYPE)='POINT' THEN 'GEOMETRY'");
sqlBuf.append(" WHEN UPPER(DATA_TYPE)='LINESTRING' THEN 'GEOMETRY'");
sqlBuf.append(" WHEN UPPER(DATA_TYPE)='POLYGON' THEN 'GEOMETRY'");
sqlBuf.append(" WHEN UPPER(DATA_TYPE)='MULTIPOINT' THEN 'GEOMETRY'");
sqlBuf.append(" WHEN UPPER(DATA_TYPE)='MULTILINESTRING' THEN 'GEOMETRY'");
sqlBuf.append(" WHEN UPPER(DATA_TYPE)='MULTIPOLYGON' THEN 'GEOMETRY'");
sqlBuf.append(" WHEN UPPER(DATA_TYPE)='GEOMETRYCOLLECTION' THEN 'GEOMETRY'");
sqlBuf.append(" WHEN UPPER(DATA_TYPE)='GEOMCOLLECTION' THEN 'GEOMETRY'");
sqlBuf.append(" ELSE UPPER(DATA_TYPE) END) AS TYPE_NAME,");
// PRECISION
sqlBuf.append(" CASE WHEN LCASE(DATA_TYPE)='date' THEN 0");
if (supportsFractSeconds) {
sqlBuf.append(" WHEN LCASE(DATA_TYPE)='time' OR LCASE(DATA_TYPE)='datetime' OR LCASE(DATA_TYPE)='timestamp' THEN DATETIME_PRECISION");
} else {
sqlBuf.append(" WHEN LCASE(DATA_TYPE)='time' OR LCASE(DATA_TYPE)='datetime' OR LCASE(DATA_TYPE)='timestamp' THEN 0");
}
if (this.tinyInt1isBit && !this.transformedBitIsBoolean) {
sqlBuf.append(
" WHEN (UPPER(DATA_TYPE)='TINYINT' AND LOCATE('ZEROFILL', UPPER(DTD_IDENTIFIER)) = 0) AND LOCATE('UNSIGNED', UPPER(DTD_IDENTIFIER)) = 0 AND LOCATE('(1)', DTD_IDENTIFIER) != 0 THEN 1");
}
// workaround for Bug#69042 (16712664), "MEDIUMINT PRECISION/TYPE INCORRECT IN INFORMATION_SCHEMA.COLUMNS", I_S bug returns NUMERIC_PRECISION=7 for MEDIUMINT UNSIGNED when it must be 8.
sqlBuf.append(" WHEN UPPER(DATA_TYPE)='MEDIUMINT' AND LOCATE('UNSIGNED', UPPER(DTD_IDENTIFIER)) != 0 THEN 8");
sqlBuf.append(" WHEN UPPER(DATA_TYPE)='JSON' THEN 1073741824"); // JSON columns is limited to the value of the max_allowed_packet system variable (max value 1073741824)
sqlBuf.append(" ELSE NUMERIC_PRECISION END AS `PRECISION`,"); //
// LENGTH
sqlBuf.append(" CASE WHEN LCASE(DATA_TYPE)='date' THEN 10");
if (supportsFractSeconds) {
sqlBuf.append(" WHEN LCASE(DATA_TYPE)='time' THEN 8+(CASE WHEN DATETIME_PRECISION>0 THEN DATETIME_PRECISION+1 ELSE DATETIME_PRECISION END)");
sqlBuf.append(" WHEN LCASE(DATA_TYPE)='datetime' OR LCASE(DATA_TYPE)='timestamp'");
sqlBuf.append(" THEN 19+(CASE WHEN DATETIME_PRECISION>0 THEN DATETIME_PRECISION+1 ELSE DATETIME_PRECISION END)");
} else {
sqlBuf.append(" WHEN LCASE(DATA_TYPE)='time' THEN 8");
sqlBuf.append(" WHEN LCASE(DATA_TYPE)='datetime' OR LCASE(DATA_TYPE)='timestamp' THEN 19");
}
if (this.tinyInt1isBit && !this.transformedBitIsBoolean) {
sqlBuf.append(
" WHEN (UPPER(DATA_TYPE)='TINYINT' OR UPPER(DATA_TYPE)='TINYINT UNSIGNED') AND LOCATE('ZEROFILL', UPPER(DTD_IDENTIFIER)) = 0 AND LOCATE('UNSIGNED', UPPER(DTD_IDENTIFIER)) = 0 AND LOCATE('(1)', DTD_IDENTIFIER) != 0 THEN 1");
}
// workaround for Bug#69042 (16712664), "MEDIUMINT PRECISION/TYPE INCORRECT IN INFORMATION_SCHEMA.COLUMNS", I_S bug returns NUMERIC_PRECISION=7 for MEDIUMINT UNSIGNED when it must be 8.
sqlBuf.append(" WHEN UPPER(DATA_TYPE)='MEDIUMINT' AND LOCATE('UNSIGNED', UPPER(DTD_IDENTIFIER)) != 0 THEN 8");
sqlBuf.append(" WHEN UPPER(DATA_TYPE)='JSON' THEN 1073741824"); // JSON columns is limited to the value of the max_allowed_packet system variable (max value 1073741824)
sqlBuf.append(" WHEN CHARACTER_MAXIMUM_LENGTH IS NULL THEN NUMERIC_PRECISION");
sqlBuf.append(" WHEN CHARACTER_MAXIMUM_LENGTH > ");
sqlBuf.append(Integer.MAX_VALUE);
sqlBuf.append(" THEN ");
sqlBuf.append(Integer.MAX_VALUE);
sqlBuf.append(" ELSE CHARACTER_MAXIMUM_LENGTH END AS LENGTH,"); //
sqlBuf.append("NUMERIC_SCALE AS `SCALE`, ");
sqlBuf.append("10 AS RADIX,");
sqlBuf.append(procedureNullable);
sqlBuf.append(" AS `NULLABLE`, NULL AS `REMARKS`, NULL AS `COLUMN_DEF`, NULL AS `SQL_DATA_TYPE`, NULL AS `SQL_DATETIME_SUB`,");
sqlBuf.append(" CHARACTER_OCTET_LENGTH AS `CHAR_OCTET_LENGTH`, ORDINAL_POSITION, 'YES' AS `IS_NULLABLE`, SPECIFIC_NAME");
sqlBuf.append(" FROM INFORMATION_SCHEMA.PARAMETERS");
StringBuilder conditionBuf = new StringBuilder();
if (!this.conn.getPropertySet().getBooleanProperty(PropertyKey.getProceduresReturnsFunctions).getValue()) {
conditionBuf.append(" ROUTINE_TYPE = 'PROCEDURE'");
}
if (db != null) {
if (conditionBuf.length() > 0) {
conditionBuf.append(" AND");
}
conditionBuf.append(this.databaseTerm.getValue() == DatabaseTerm.SCHEMA ? " SPECIFIC_SCHEMA LIKE ?" : " SPECIFIC_SCHEMA = ?");
}
if (procedureNamePattern != null) {
if (conditionBuf.length() > 0) {
conditionBuf.append(" AND");
}
conditionBuf.append(" SPECIFIC_NAME LIKE ?");
}
if (columnNamePattern != null) {
if (conditionBuf.length() > 0) {
conditionBuf.append(" AND");
}
conditionBuf.append(" (PARAMETER_NAME LIKE ? OR PARAMETER_NAME IS NULL)");
}
if (conditionBuf.length() > 0) {
sqlBuf.append(" WHERE");
sqlBuf.append(conditionBuf);
}
sqlBuf.append(" ORDER BY SPECIFIC_SCHEMA, SPECIFIC_NAME, ROUTINE_TYPE, ORDINAL_POSITION");
java.sql.PreparedStatement pStmt = null;
try {
pStmt = prepareMetaDataSafeStatement(sqlBuf.toString());
int nextId = 1;
if (db != null) {
pStmt.setString(nextId++, db);
}
if (procedureNamePattern != null) {
pStmt.setString(nextId++, procedureNamePattern);
}
if (columnNamePattern != null) {
pStmt.setString(nextId, columnNamePattern);
}
ResultSet rs = executeMetadataQuery(pStmt);
((com.mysql.cj.jdbc.result.ResultSetInternalMethods) rs).getColumnDefinition().setFields(createProcedureColumnsFields());
return rs;
} finally {
if (pStmt != null) {
pStmt.close();
}
}
}