fix index ount of bound panic.
https://github.com/grafana/loki/pull/5692/
[new feature] Index: loki support apache calcite avatica index storage. #5692
I implemented the index storage plugin of apache avatic in the grafana loki community, and found that avatica-go would panic in the online environment. This PR attempts to fix this panic. Our online loki has been fixed.
panic: runtime error: index out of range [0] with length 0
/usr/local/go/src/runtime/panic.go:1038 +0x215
github.com/apache/calcite-avatica-go/v5.(*rows).Columns(0x4cc4b7)
/Users/fuling/go/pkg/mod/github.com/liguozhong/calcite-avatica-go/[email protected]/rows.go:55 +0x17b
database/sql.(*Rows).nextLocked(0xc038348000)
/usr/local/go/src/database/sql/sql.go:2964 +0xb0
database/sql.(*Rows).Next.func1()
/usr/local/go/src/database/sql/sql.go:2945 +0x2f
database/sql.withLock({0x32a6008, 0xc038348030}, 0xc004cb76f0)
/usr/local/go/src/database/sql/sql.go:3396 +0x8c
database/sql.(*Rows).Next(0xc038348000)
/usr/local/go/src/database/sql/sql.go:2944 +0x6f
github.com/grafana/loki/pkg/storage/chunk/avatica.(*StorageClient).query(0xc001024ea0, {0x32d98a8, 0xc0188ef320}, {{0xc00589f300, 0x1e}, {0xc01bc60990, 0x2b}, {0x0, 0x0, 0x0}, ...}, ...)
code in loki, for rows.Next() { panic.
case query.ValueEqual != nil:
querySQL = fmt.Sprintf("SELECT range, value FROM %s WHERE hash = ? AND value = ? ALLOW FILTERING",
query.TableName)
queryFunc = func() error {
rows, err = s.readSession.QueryContext(ctx, querySQL, query.HashValue, query.ValueEqual)
return err
}
}
retries := backoff.New(ctx, s.cfg.BackoffConfig)
err = ctx.Err()
for retries.Ongoing() {
err = s.queryInstrumentation(ctx, querySQL, queryFunc)
if err == nil {
break
}
retries.Wait()
}
if err != nil {
level.Error(util_log.Logger).Log("msg", "avatica QUERY fail", "sql", querySQL, "err", err)
return errors.WithStack(err)
}
defer rows.Close()
for rows.Next() {
b := &readBatch{}
err = rows.Scan(&b.rangeValue, &b.value)
if err != nil {
return errors.WithStack(err)
}
if !callback(query, b) {
return nil
}
}
func (s *StorageClient) queryInstrumentation(ctx context.Context, query string, queryFunc func() error) error {
var start time.Time
var end time.Time
var err error
sp := ot.SpanFromContext(ctx)
sp.SetTag("sql", query)
defer func() {
statusCode := "200"
if err != nil {
level.Warn(util_log.Logger).Log("msg", "avatica query fail", "sql", query, "err", err)
statusCode = "500"
ext.Error.Set(sp, true)
sp.LogFields(otlog.String("event", "error"), otlog.String("message", err.Error()))
}
parts := strings.SplitN(query, " ", 2)
requestDuration.WithLabelValues(parts[0], statusCode).Observe(end.Sub(start).Seconds())
}()
start = time.Now()
err = queryFunc()
end = time.Now()
if err != nil {
return errors.WithStack(err)
}
return nil
}