Skip to content

Commit f678a2a

Browse files
Merge branch 'master' into properly-display-or-hide-tenant-info
2 parents 93ed3a1 + 130f5b8 commit f678a2a

File tree

5 files changed

+34
-5
lines changed

5 files changed

+34
-5
lines changed

docs/victorialogs/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ according to [these docs](https://docs.victoriametrics.com/victorialogs/quicksta
2020

2121
* FEATURE: [web UI](https://docs.victoriametrics.com/victorialogs/querying/#web-ui): set proper tenant information, when `AccountID` and `ProjectID` headers are set by a proxy or completely hide it in UI if `-select.disableTenantResponseHeaders` flag is set. See [#656](https://github.com/VictoriaMetrics/VictoriaLogs/issues/656)
2222

23+
* BUGFIX: [`/select/logsql/query` endpoint](https://docs.victoriametrics.com/victorialogs/querying/#querying-logs): properly optimize the query execution when the `limit` query arg is set, while the `offset` query arg isn't set. It wasn't addressed properly in [v1.33.0](#v1330). See [#620](https://github.com/VictoriaMetrics/VictoriaLogs/issues/620).
24+
2325
## [v1.33.0](https://github.com/VictoriaMetrics/VictoriaLogs/releases/tag/v1.33.0)
2426

2527
Released at 2025-09-10

lib/logstorage/net_query_runner_test.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,4 +84,9 @@ func TestSplitQueryToRemoteAndLocal(t *testing.T) {
8484
f(`foo | unpack_syslog`, `foo | unpack_syslog`, ``)
8585
f(`foo | unpack_words`, `foo | unpack_words`, ``)
8686
f(`foo | unroll by (x)`, `foo | unroll by (x)`, ``)
87+
88+
// Special cases with 'offset 0'
89+
// See https://github.com/VictoriaMetrics/VictoriaLogs/issues/620#issuecomment-3276624504
90+
f(`foo | offset 0`, `foo`, ``)
91+
f(`foo | offset 0 | limit 10`, `foo | limit 10`, `limit 10`)
8792
}

lib/logstorage/parser.go

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -790,7 +790,7 @@ func (q *Query) AddPipeOffsetLimit(offset, limit uint64) {
790790
q.mustAppendPipe(limitStr)
791791

792792
// optimize the query, so the `offset` and `limit` pipes could be joined with the preceding `sort` pipe.
793-
q.pipes = optimizeSortOffsetLimitPipes(q.pipes)
793+
q.pipes = optimizeOffsetLimitPipes(q.pipes)
794794
}
795795

796796
func (q *Query) mustAppendPipe(s string) {
@@ -807,7 +807,7 @@ func (q *Query) optimize() {
807807
}
808808

809809
func (q *Query) optimizeNoSubqueries() {
810-
q.pipes = optimizeSortOffsetLimitPipes(q.pipes)
810+
q.pipes = optimizeOffsetLimitPipes(q.pipes)
811811
q.pipes = optimizeUniqLimitPipes(q.pipes)
812812
q.pipes = optimizeFilterPipes(q.pipes)
813813

@@ -1323,15 +1323,28 @@ func removeStarFilters(f filter) filter {
13231323
return f
13241324
}
13251325

1326-
func optimizeSortOffsetLimitPipes(pipes []pipe) []pipe {
1326+
func optimizeOffsetLimitPipes(pipes []pipe) []pipe {
13271327
for {
13281328
pipesLen := len(pipes)
13291329
pipes = optimizeSortOffsetPipes(pipes)
13301330
pipes = optimizeSortLimitPipes(pipes)
13311331
if len(pipes) == pipesLen {
1332-
return pipes
1332+
break
13331333
}
13341334
}
1335+
1336+
// Remove `offset 0` pipes.
1337+
i := 0
1338+
for i < len(pipes) {
1339+
po, ok := pipes[i].(*pipeOffset)
1340+
if !ok || po.offset != 0 {
1341+
i++
1342+
continue
1343+
}
1344+
pipes = append(pipes[:i], pipes[i+1:]...)
1345+
}
1346+
1347+
return pipes
13351348
}
13361349

13371350
func optimizeSortOffsetPipes(pipes []pipe) []pipe {

lib/logstorage/parser_test.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,7 @@ func TestQuery_AddTimeFilter_StepPropagation(t *testing.T) {
355355
})
356356
}
357357

358-
func TestParseQuery_OptimizeSortOffsetLimitPipes(t *testing.T) {
358+
func TestParseQuery_OptimizeOffsetLimitPipes(t *testing.T) {
359359
f := func(s, resultExpected string) {
360360
t.Helper()
361361

@@ -385,6 +385,11 @@ func TestParseQuery_OptimizeSortOffsetLimitPipes(t *testing.T) {
385385
f(`* | sort by (x) | limit 30 | limit 20 | offset 4`, `* | sort by (x) offset 4 limit 16`)
386386
f(`* | sort by (x) | limit 30 | limit 20 | offset 4 | offset 5`, `* | sort by (x) offset 9 limit 11`)
387387
f(`* | sort by (x) | limit 30 | limit 20 | offset 4 | offset 5 | fields x`, `* | sort by (x) offset 9 limit 11 | fields x`)
388+
389+
// Verify the case without 'sort' pipe and with 'offset 0' pipes.
390+
// See https://github.com/VictoriaMetrics/VictoriaLogs/issues/620#issuecomment-3276624504
391+
f(`* | offset 0`, `*`)
392+
f(`* | offset 0 | limit 10`, `* | limit 10`)
388393
}
389394

390395
func TestParseQuery_OptimizeStarFilters(t *testing.T) {

lib/logstorage/pipe_offset.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ func (po *pipeOffset) String() string {
1919
}
2020

2121
func (po *pipeOffset) splitToRemoteAndLocal(_ int64) (pipe, []pipe) {
22+
if po.offset == 0 {
23+
// Special case - `offset 0` is safe to push to the remote side.
24+
return po, nil
25+
}
2226
return nil, []pipe{po}
2327
}
2428

0 commit comments

Comments
 (0)