private CompletableFuture<Schema> readTableMetadata(
            Schema schema,
            CompletableFuture<Map<String, Class<?>>> typeMappingTask,
            ProgressMeasure progress) {

        final CompletableFuture<Void> tablesTask = CompletableFuture.runAsync(() ->
            tablesTask(schema)
        );

        return tablesTask.thenComposeAsync(unused -> typeMappingTask)
            .thenComposeAsync(sqlTypeMappings -> {
                final Dbms dbms = schema.getParentOrThrow();
                final AtomicInteger cnt = new AtomicInteger();
                final double noTables = schema.tables().count();

                return CompletableFuture.allOf(
                    schema.tables().map(table -> CompletableFuture.runAsync(() -> {
                        try (final Connection conn = connectionPool.getConnection(dbms)) {
                            progress.setCurrentAction(describe(table));
                            columns(conn, sqlTypeMappings, table, progress);
                            indexes(conn, table, progress);
                            foreignKeys(conn, table);
                            primaryKeyColumns(conn, table, progress);

                            if (!table.isView()) {

                                // If no INTEGER PRIMARY KEY exists, a rowId should be created.
                                if (table.columns()
                                    .filter(col -> col.getAsString(ORIGINAL_TYPE).filter("INTEGER"::equalsIgnoreCase).isPresent())
                                    .noneMatch(col -> table.primaryKeyColumns().anyMatch(pkc -> DocumentDbUtil.isSame(pkc.findColumnOrThrow(), col)))
                                &&  table.columns().map(Column::getId).noneMatch(ROW_ID::equalsIgnoreCase)) {
                                    createRowId(table);
                                } else {
                                    table.columns()
                                        .filter(col -> col.getAsString(ORIGINAL_TYPE).filter("INTEGER"::equalsIgnoreCase).isPresent())
                                        .filter(col -> table.primaryKeyColumns().anyMatch(pkc -> DocumentDbUtil.isSame(pkc.findColumnOrThrow(), col)))
                                        .forEach(col -> col.mutator().setAutoIncrement(true));
                                }
                            }

                            table.columns().forEach(col ->
                                col.getData().remove(ORIGINAL_TYPE)
                            );

                            progress.setProgress(cnt.incrementAndGet() / noTables);
                        } catch (final SQLException ex) {
                            throw new SpeedmentException(ex);
                        }
                    })).toArray(CompletableFuture[]::new)
                ).thenApplyAsync(v -> schema);
            });
    }
'true' below might speed up metadata retrieval since approximations can
be used. See https://github.com/speedment/speedment-enterprise/issues/168
runtime-parent/runtime-connector-parent/sqlite/src/main/java/com/speedment/runtime/connector/sqlite/internal/SqliteMetadataHandlerImpl.java