protected void columns(
        final Connection connection, 
        final Map<String, Class<?>> sqlTypeMapping, 
        final Table table, 
        final ProgressMeasure progressListener
    ) {
        requireNonNulls(connection, table);

        final Schema schema = table.getParentOrThrow();

        final SqlSupplier<ResultSet> supplier = ()
            -> connection.getMetaData().getColumns(
                jdbcCatalogLookupName(schema),
                jdbcSchemaLookupName(schema),
                metaDataTableNameForColumns(table),
                null
            );

        final TableChildMutator<Column, ResultSet> mutator = (column, rs) -> {

            final ColumnMetaData md = ColumnMetaData.of(rs);

            final String columnName = md.getColumnName();
            
            column.mutator().setId(columnName);
            column.mutator().setName(columnName);
            column.mutator().setOrdinalPosition(md.getOrdinalPosition());

            final boolean nullable;
            final int nullableValue = md.getNullable();

            if (nullableValue == columnNullable ||
                nullableValue == columnNullableUnknown) {
                nullable = true;
            } else if (nullableValue == columnNoNulls) {
                nullable = false;
            } else {
                throw new SpeedmentException("Unknown nullable type " + nullableValue);
            }

            column.mutator().setNullable(nullable);

            final Class<?> lookupJdbcClass = javaTypeMap.findJdbcType(sqlTypeMapping, md);

            final Class<?> selectedJdbcClass;
            if (lookupJdbcClass != null) {
                selectedJdbcClass = lookupJdbcClass;
            } else {
                // Fall-back to DEFAULT_MAPPING
                selectedJdbcClass = DEFAULT_MAPPING;
                LOGGER.warn(
                    String.format("Unable to determine mapping for table %s, column %s. "
                        + "Type name %s, data type %d, decimal digits %d."
                        + "Fallback to JDBC-type %s",
                        table.getId(),
                        column.getId(),
                        md.getTypeName(),
                        md.getDataType(),
                        md.getDecimalDigits(),
                        selectedJdbcClass.getSimpleName()
                    )
                );                    
            }

            column.mutator().setDatabaseType(selectedJdbcClass);

            if (!nullable && hasPrimitiveClass(selectedJdbcClass)) {
                column.mutator().setTypeMapper(TypeMapper.primitive().getClass());
            }
            
            if ("ENUM".equalsIgnoreCase(md.getTypeName())) {
                final Dbms dbms = schema.getParentOrThrow();
                final List<String> constants = enumConstantsOf(dbms, table, columnName);
                column.mutator().setEnumConstants(constants.stream().collect(joining(",")));
            }

            setAutoIncrement(column, md);
            progressListener.setCurrentAction(actionName(column));
            extraInfo("columns(,, %s, ...) read %s", table.getId(), column);
        };

        tableChilds(Column.class, table.mutator()::addNewColumn, supplier, mutator, progressListener);
    }
@author  Emil Forslund
@author  Per Minborg
@since   3.0.0
runtime-parent/runtime-core/src/main/java/com/speedment/runtime/core/abstracts/AbstractDbmsMetadataHandler.java