private List extractForeignKeysFromCreateTable()

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;
    }