private async Task <IReadOnlyCollection <IDatabaseIndex> > LoadIndexesAsyncCore(Identifier tableName, PostgreSqlTableQueryCache queryCache, CancellationToken cancellationToken)
        {
            var queryResult = await DbConnection.QueryAsync <IndexColumns>(
                IndexesQuery,
                new { SchemaName = tableName.Schema, TableName = tableName.LocalName },
                cancellationToken
                ).ConfigureAwait(false);

            if (queryResult.Empty())
            {
                return(Array.Empty <IDatabaseIndex>());
            }

            var indexColumns = queryResult.GroupBy(row => new { row.IndexName, row.IsUnique, row.IsPrimary, row.KeyColumnCount }).ToList();

            if (indexColumns.Empty())
            {
                return(Array.Empty <IDatabaseIndex>());
            }

            var columns = await queryCache.GetColumnsAsync(tableName, cancellationToken).ConfigureAwait(false);

            var columnLookup = GetColumnLookup(columns);

            var result = new List <IDatabaseIndex>(indexColumns.Count);

            foreach (var indexInfo in indexColumns)
            {
                var isUnique  = indexInfo.Key.IsUnique;
                var indexName = Identifier.CreateQualifiedIdentifier(indexInfo.Key.IndexName);

                var indexCols = indexInfo
                                .OrderBy(row => row.IndexColumnId)
                                .Where(row => row.IndexColumnExpression != null)
                                .Select(row => new
                {
                    row.IsDescending,
                    Expression = row.IndexColumnExpression,
                    Column     = row.IndexColumnExpression != null && columnLookup.ContainsKey(row.IndexColumnExpression)
                            ? columnLookup[row.IndexColumnExpression]
                            : null
                })
                                .Select(row =>
                {
                    var order      = row.IsDescending ? IndexColumnOrder.Descending : IndexColumnOrder.Ascending;
                    var expression = row.Column != null
                            ? Dialect.QuoteName(row.Column.Name)
                            : row.Expression !;
                    return(row.Column != null
                            ? new PostgreSqlDatabaseIndexColumn(expression, row.Column, order)
                            : new PostgreSqlDatabaseIndexColumn(expression, order));
                })
                                .Take(indexInfo.Key.KeyColumnCount)
                                .ToList();
                var includedCols = indexInfo
                                   .OrderBy(row => row.IndexColumnId)
                                   .Skip(indexInfo.Key.KeyColumnCount)
                                   .Where(row => row.IndexColumnExpression != null && columnLookup.ContainsKey(row.IndexColumnExpression))
                                   .Select(row => columnLookup[row.IndexColumnExpression !])
        /// <summary>
        /// Retrieves indexes that relate to the given table.
        /// </summary>
        /// <param name="tableName">A table name.</param>
        /// <param name="queryCache">A query cache for the given context.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>A collection of indexes.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="tableName"/> or <paramref name="queryCache"/> are <c>null</c>.</exception>
        protected override Task <IReadOnlyCollection <IDatabaseIndex> > LoadIndexesAsync(Identifier tableName, PostgreSqlTableQueryCache queryCache, CancellationToken cancellationToken)
        {
            if (tableName == null)
            {
                throw new ArgumentNullException(nameof(tableName));
            }
            if (queryCache == null)
            {
                throw new ArgumentNullException(nameof(queryCache));
            }

            return(LoadIndexesAsyncCore(tableName, queryCache, cancellationToken));
        }