mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2024-12-31 15:06:26 +00:00
wip
This commit is contained in:
parent
9af6c63774
commit
401e79e0d8
5 changed files with 34 additions and 13 deletions
|
@ -19,6 +19,8 @@ according to [these docs](https://docs.victoriametrics.com/victorialogs/quicksta
|
|||
|
||||
## tip
|
||||
|
||||
* FEATURE: allow [`head` pipe](https://docs.victoriametrics.com/victorialogs/logsql/#limit-pipe) without number. For example, `error | head`. In this case 10 last values are returned as `head` Unix command does by default.
|
||||
|
||||
## [v0.12.1](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v0.12.1-victorialogs)
|
||||
|
||||
Released at 2024-05-26
|
||||
|
|
|
@ -1463,6 +1463,12 @@ _time:5m | limit 100
|
|||
|
||||
`head` keyword can be used instead of `limit` for convenience. For example, `_time:5m | head 100` is equivalent to `_time:5m | limit 100`.
|
||||
|
||||
The `N` in `head N` can be omitted - in this case up to 10 matching logs are returned:
|
||||
|
||||
```logsql
|
||||
error | head
|
||||
```
|
||||
|
||||
By default rows are selected in arbitrary order because of performance reasons, so the query above can return different sets of logs every time it is executed.
|
||||
[`sort` pipe](#sort-pipe) can be used for making sure the logs are in the same order before applying `limit ...` to them.
|
||||
|
||||
|
|
|
@ -869,8 +869,10 @@ func TestParseQuerySuccess(t *testing.T) {
|
|||
f(`* | DELETE foo, bar`, `* | delete foo, bar`)
|
||||
|
||||
// limit and head pipe
|
||||
f(`foo | limit 10`, `foo | limit 10`)
|
||||
f(`foo | head 10`, `foo | limit 10`)
|
||||
f(`foo | limit`, `foo | limit 10`)
|
||||
f(`foo | head`, `foo | limit 10`)
|
||||
f(`foo | limit 20`, `foo | limit 20`)
|
||||
f(`foo | head 20`, `foo | limit 20`)
|
||||
f(`foo | HEAD 1_123_432`, `foo | limit 1123432`)
|
||||
f(`foo | head 10K`, `foo | limit 10000`)
|
||||
|
||||
|
@ -1313,10 +1315,6 @@ func TestParseQueryFailure(t *testing.T) {
|
|||
f(`foo | delete foo,`)
|
||||
f(`foo | delete foo,,`)
|
||||
|
||||
// missing limit and head pipe value
|
||||
f(`foo | limit`)
|
||||
f(`foo | head`)
|
||||
|
||||
// invalid limit pipe value
|
||||
f(`foo | limit bar`)
|
||||
f(`foo | limit -123`)
|
||||
|
|
|
@ -88,15 +88,20 @@ func parsePipeLimit(lex *lexer) (*pipeLimit, error) {
|
|||
if !lex.isKeyword("limit", "head") {
|
||||
return nil, fmt.Errorf("expecting 'limit' or 'head'; got %q", lex.token)
|
||||
}
|
||||
lex.nextToken()
|
||||
|
||||
lex.nextToken()
|
||||
n, err := parseUint(lex.token)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot parse rows limit from %q: %w", lex.token, err)
|
||||
limit := uint64(10)
|
||||
if !lex.isKeyword("|", ")", "") {
|
||||
n, err := parseUint(lex.token)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot parse rows limit from %q: %w", lex.token, err)
|
||||
}
|
||||
lex.nextToken()
|
||||
limit = n
|
||||
}
|
||||
lex.nextToken()
|
||||
|
||||
pl := &pipeLimit{
|
||||
limit: n,
|
||||
limit: limit,
|
||||
}
|
||||
return pl, nil
|
||||
}
|
||||
|
|
|
@ -20,7 +20,6 @@ func TestParsePipeLimitFailure(t *testing.T) {
|
|||
expectParsePipeFailure(t, pipeStr)
|
||||
}
|
||||
|
||||
f(`limit`)
|
||||
f(`limit -10`)
|
||||
f(`limit foo`)
|
||||
}
|
||||
|
@ -30,6 +29,17 @@ func TestPipeLimit(t *testing.T) {
|
|||
t.Helper()
|
||||
expectPipeResults(t, pipeStr, rows, rowsExpected)
|
||||
}
|
||||
f("limit", [][]Field{
|
||||
{
|
||||
{"_msg", `{"foo":"bar"}`},
|
||||
{"a", `test`},
|
||||
},
|
||||
}, [][]Field{
|
||||
{
|
||||
{"_msg", `{"foo":"bar"}`},
|
||||
{"a", `test`},
|
||||
},
|
||||
})
|
||||
|
||||
f("limit 100", [][]Field{
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue