in src/main/user-impl/java/com/mysql/cj/jdbc/DatabaseMetaDataMysqlSchema.java [513:617]
private List<ForeignKeyConstraintInfo> extractForeignKeysFromCreateTable(String dbName, String tableName, String createTableSql) throws SQLException {
Function<String, Integer> mysqlActionToJdbc = action -> {
if (action.startsWith("NO ACTION")) {
return importedKeyNoAction;
} else if (action.startsWith("CASCADE")) {
return importedKeyCascade;
} else if (action.startsWith("SET NULL")) {
return importedKeySetNull;
} else if (action.startsWith("SET DEFAULT")) {
return importedKeySetDefault;
}
return importedKeyRestrict; // RESTRICT
};
List<ForeignKeyConstraintInfo> tableForeignKeysList = new ArrayList<>();
StringTokenizer lineTokenizer = new StringTokenizer(createTableSql, "\n");
while (lineTokenizer.hasMoreTokens()) {
String line = lineTokenizer.nextToken().trim();
String constraintName = null;
List<String> referencingColumnNames;
String referencedDbName = StringUtils.quoteIdentifier(dbName, getQuoteId(), true);
String referencedTableName = "";
List<String> referencedColumnNames;
int referentialActionOnDelete = importedKeyRestrict;
int referentialActionOnUpdate = importedKeyRestrict;
if (StringUtils.startsWithIgnoreCase(line, "CONSTRAINT")) {
int beginPos = line.indexOf(getQuoteId());
if (beginPos != -1) {
int endPos = -1;
endPos = StringUtils.indexOfQuoteDoubleAware(line, getQuoteId(), beginPos + 1);
if (endPos != -1) {
constraintName = StringUtils.unquoteIdentifier(line.substring(beginPos + 1, endPos), getQuoteId());
line = line.substring(endPos + 1, line.length()).trim();
}
}
}
if (line.startsWith("FOREIGN KEY")) {
int afterFk = "FOREIGN KEY".length();
int referencingColumnsBegin = StringUtils.indexOfIgnoreCase(afterFk, line, "(", getQuoteId(), getQuoteId(),
SearchMode.__BSE_MRK_COM_MYM_HNT_WS);
if (referencingColumnsBegin == -1) {
throw SQLError.createSQLException(Messages.getString("DatabaseMetaData.14"), MysqlErrorNumbers.SQLSTATE_CONNJ_GENERAL_ERROR,
getExceptionInterceptor());
}
int referencingColumnsEnd = StringUtils.indexOfIgnoreCase(referencingColumnsBegin, line, ")", getQuoteId(), getQuoteId(),
SearchMode.__BSE_MRK_COM_MYM_HNT_WS);
if (referencingColumnsEnd == -1) {
throw SQLError.createSQLException(Messages.getString("DatabaseMetaData.15"), MysqlErrorNumbers.SQLSTATE_CONNJ_GENERAL_ERROR,
getExceptionInterceptor());
}
String referencingColumnNamesToken = line.substring(referencingColumnsBegin + 1, referencingColumnsEnd);
referencingColumnNames = StringUtils.split(referencingColumnNamesToken, ",", getQuoteId(), getQuoteId(), false).stream()
.map(c -> StringUtils.unquoteIdentifier(c, getQuoteId())).collect(Collectors.toList());
int indexOfRef = StringUtils.indexOfIgnoreCase(afterFk, line, "REFERENCES", getQuoteId(), getQuoteId(), SearchMode.__BSE_MRK_COM_MYM_HNT_WS);
if (indexOfRef == -1) {
throw SQLError.createSQLException(Messages.getString("DatabaseMetaData.16"), MysqlErrorNumbers.SQLSTATE_CONNJ_GENERAL_ERROR,
getExceptionInterceptor());
}
int afterRef = indexOfRef + "REFERENCES".length();
int referencedColumnsBegin = StringUtils.indexOfIgnoreCase(afterRef, line, "(", getQuoteId(), getQuoteId(),
SearchMode.__BSE_MRK_COM_MYM_HNT_WS);
if (referencedColumnsBegin == -1) {
throw SQLError.createSQLException(Messages.getString("DatabaseMetaData.17"), MysqlErrorNumbers.SQLSTATE_CONNJ_GENERAL_ERROR,
getExceptionInterceptor());
}
referencedTableName = line.substring(afterRef, referencedColumnsBegin).trim();
int referencedColumnsEnd = StringUtils.indexOfIgnoreCase(referencedColumnsBegin + 1, line, ")", getQuoteId(), getQuoteId(),
SearchMode.__BSE_MRK_COM_MYM_HNT_WS);
if (referencedColumnsEnd == -1) {
throw SQLError.createSQLException(Messages.getString("DatabaseMetaData.18"), MysqlErrorNumbers.SQLSTATE_CONNJ_GENERAL_ERROR,
getExceptionInterceptor());
}
String referencedColumnNamesToken = line.substring(referencedColumnsBegin + 1, referencedColumnsEnd);
referencedColumnNames = StringUtils.split(referencedColumnNamesToken, ",", getQuoteId(), getQuoteId(), false).stream()
.map(c -> StringUtils.unquoteIdentifier(c, getQuoteId())).collect(Collectors.toList());
if (referencedColumnNames.size() != referencingColumnNames.size()) {
throw SQLError.createSQLException(Messages.getString("DatabaseMetaData.12"), MysqlErrorNumbers.SQLSTATE_CONNJ_GENERAL_ERROR,
getExceptionInterceptor());
}
List<String> tableRef = StringUtils.splitDBdotName(referencedTableName, referencedDbName, getQuoteId(), true);
referencedDbName = StringUtils.unquoteIdentifier(tableRef.get(0), getQuoteId());
referencedTableName = StringUtils.unquoteIdentifier(tableRef.get(1), getQuoteId());
String referentialActions = line.substring(referencedColumnsEnd + 1);
int onDeletePos = referentialActions.indexOf("ON DELETE");
if (onDeletePos != -1) {
int afterOnDelete = onDeletePos + "ON DELETE ".length();
String onDeleteAction = referentialActions.substring(afterOnDelete);
referentialActionOnDelete = mysqlActionToJdbc.apply(onDeleteAction);
}
int onUpdatePos = referentialActions.indexOf("ON UPDATE");
if (onUpdatePos != -1) {
int afterOnUpdate = onUpdatePos + "ON UPDATE ".length();
String onUpdateAction = referentialActions.substring(afterOnUpdate);
referentialActionOnUpdate = mysqlActionToJdbc.apply(onUpdateAction);
}
tableForeignKeysList.add(new ForeignKeyConstraintInfo(constraintName, dbName, tableName, referencingColumnNames, referencedDbName,
referencedTableName, referencedColumnNames, referentialActionOnDelete, referentialActionOnUpdate));
}
}
return tableForeignKeysList;
}