/// <inheritdoc/>
        public QueryItemsOf <T> ExecuteSql <T>(string sql, Func <byte[], T> deserializeItem)
        {
            var result = new QueryItemsOf <T>
            {
                Items = new List <T>()
            };

            using (var sqlRx = sql.GetHandle())
            {
                var rsp = Assert.ThrowIfError(() => ReindexerBinding.reindexer_select(Rx, sqlRx, 1, new int[0], 0, _ctxInfo));
                try
                {
                    var reader         = new CJsonReader(rsp.@out);
                    var rawQueryParams = reader.ReadRawQueryParams();
                    var explain        = rawQueryParams.explainResults;

                    result.QueryTotalItems = rawQueryParams.totalcount != 0 ? rawQueryParams.totalcount : rawQueryParams.count;
                    if (explain.Length > 0)
                    {
                        result.Explain = JsonSerializer.Deserialize <ExplainDef>(explain.ToArray(), //todo: use span when utf8json supports it.
                                                                                 StandardResolver.ExcludeNull);
                    }

                    for (var i = 0; i < rawQueryParams.count; i++)
                    {
                        var item = reader.ReadRawItemParams();
                        if (item.data.Length > 0)
                        {
                            result.Items.Add(deserializeItem(item.data.ToArray())); //todo: use span when utf8json supports it.
                        }
                    }

                    if ((rawQueryParams.flags & CJsonReader.ResultsWithJoined) != 0 && reader.GetVarUInt() != 0)
                    {
                        throw new NotImplementedException("Sorry, not implemented: Can't return join query results as json");
                    }

                    return(result);
                }
                finally
                {
                    [email protected]();
                }
            }
        }