diff --git a/lib/logstorage/fields_set.go b/lib/logstorage/fields_set.go index faf52ce9d..cb1194f6e 100644 --- a/lib/logstorage/fields_set.go +++ b/lib/logstorage/fields_set.go @@ -28,6 +28,10 @@ func (fs fieldsSet) clone() fieldsSet { return fsNew } +func (fs fieldsSet) isEmpty() bool { + return len(fs) == 0 +} + func (fs fieldsSet) getAll() []string { a := make([]string, 0, len(fs)) for f := range fs { diff --git a/lib/logstorage/parser_test.go b/lib/logstorage/parser_test.go index 01f89c5fe..feb8f8f2f 100644 --- a/lib/logstorage/parser_test.go +++ b/lib/logstorage/parser_test.go @@ -1542,7 +1542,6 @@ func TestQueryGetNeededColumns(t *testing.T) { f(`* | fields f1, f2 | mv f1 f3, f4 f5`, `f1,f2`, ``) f(`* | fields f1, f2 | mv f2 f3, f4 f5`, `f1,f2`, ``) f(`* | fields f1, f2 | mv f2 f3, f4 f1`, `f2`, ``) - f(`* | fields f1, f2 | stats count() r1`, ``, ``) f(`* | fields f1, f2 | stats count_uniq() r1`, `f1,f2`, ``) f(`* | fields f1, f2 | stats count(f1) r1`, `f1`, ``) f(`* | fields f1, f2 | stats count(f1,f2,f3) r1`, `f1,f2`, ``) @@ -1776,11 +1775,21 @@ func TestQueryGetNeededColumns(t *testing.T) { f(`* | rm f1, f2 | mv f2 f3 | sort by(f1)`, `*`, `f1,f2,f3`) f(`* | rm f1, f2 | fields f3`, `f3`, ``) f(`* | rm f1, f2 | fields f1,f3`, `f3`, ``) - f(`* | rm f1, f2 | stats count() f1`, ``, ``) f(`* | rm f1, f2 | stats count(f3) r1`, `f3`, ``) f(`* | rm f1, f2 | stats count(f1) r1`, ``, ``) f(`* | rm f1, f2 | stats count(f1,f3) r1`, `f3`, ``) f(`* | rm f1, f2 | stats by(f1) count(f2) r1`, ``, ``) f(`* | rm f1, f2 | stats by(f3) count(f2) r1`, `f3`, ``) f(`* | rm f1, f2 | stats by(f3) count(f4) r1`, `f3,f4`, ``) + + // Verify that fields are correctly tracked before count(*) + f(`* | copy a b, c d | count() r1`, `a`, ``) + f(`* | delete a, b | count() r1`, `*`, `a`) + f(`* | extract "bar" from x | count() r1`, `x`, ``) + f(`* | extract_regexp "(?P.*)bar" from x | count() r1`, `x`, ``) + f(`* | field_names | count() r1`, `*`, `_time`) + f(`* | limit 10 | field_names as abc | count() r1`, `*`, ``) + f(`* | fields a, b | count() r1`, `a`, ``) + f(`* | field_values a | count() r1`, `a`, ``) + f(`* | limit 10 | filter a:b c:d | count() r1`, `a,c`, ``) } diff --git a/lib/logstorage/pipe_copy.go b/lib/logstorage/pipe_copy.go index 00d91edca..c3d4ffdf1 100644 --- a/lib/logstorage/pipe_copy.go +++ b/lib/logstorage/pipe_copy.go @@ -32,6 +32,11 @@ func (pc *pipeCopy) String() string { } func (pc *pipeCopy) updateNeededFields(neededFields, unneededFields fieldsSet) { + if neededFields.isEmpty() { + neededFields.add(pc.srcFields[0]) + return + } + for i := len(pc.srcFields) - 1; i >= 0; i-- { srcField := pc.srcFields[i] dstField := pc.dstFields[i] diff --git a/lib/logstorage/pipe_delete.go b/lib/logstorage/pipe_delete.go index 543b769fb..2530fb39e 100644 --- a/lib/logstorage/pipe_delete.go +++ b/lib/logstorage/pipe_delete.go @@ -23,11 +23,15 @@ func (pd *pipeDelete) String() string { } func (pd *pipeDelete) updateNeededFields(neededFields, unneededFields fieldsSet) { + if neededFields.isEmpty() { + neededFields.add("*") + unneededFields.add(pd.fields[0]) + return + } + if neededFields.contains("*") { - // update only unneeded fields unneededFields.addFields(pd.fields) } else { - // update only needed fields neededFields.removeFields(pd.fields) } } diff --git a/lib/logstorage/pipe_extract.go b/lib/logstorage/pipe_extract.go index a0cfe16f4..a2e98cee1 100644 --- a/lib/logstorage/pipe_extract.go +++ b/lib/logstorage/pipe_extract.go @@ -60,6 +60,11 @@ func (pe *pipeExtract) initFilterInValues(cache map[string][]string, getFieldVal } func (pe *pipeExtract) updateNeededFields(neededFields, unneededFields fieldsSet) { + if neededFields.isEmpty() { + neededFields.add(pe.fromField) + return + } + if neededFields.contains("*") { unneededFieldsOrig := unneededFields.clone() needFromField := false diff --git a/lib/logstorage/pipe_extract_regexp.go b/lib/logstorage/pipe_extract_regexp.go index 5a5c4017a..aec47d119 100644 --- a/lib/logstorage/pipe_extract_regexp.go +++ b/lib/logstorage/pipe_extract_regexp.go @@ -62,6 +62,11 @@ func (pe *pipeExtractRegexp) initFilterInValues(cache map[string][]string, getFi } func (pe *pipeExtractRegexp) updateNeededFields(neededFields, unneededFields fieldsSet) { + if neededFields.isEmpty() { + neededFields.add(pe.fromField) + return + } + if neededFields.contains("*") { unneededFieldsOrig := unneededFields.clone() needFromField := false diff --git a/lib/logstorage/pipe_field_values.go b/lib/logstorage/pipe_field_values.go index d9c1f57ac..b56111f55 100644 --- a/lib/logstorage/pipe_field_values.go +++ b/lib/logstorage/pipe_field_values.go @@ -22,6 +22,11 @@ func (pf *pipeFieldValues) String() string { } func (pf *pipeFieldValues) updateNeededFields(neededFields, unneededFields fieldsSet) { + if neededFields.isEmpty() { + neededFields.add(pf.field) + return + } + if neededFields.contains("*") { neededFields.reset() if !unneededFields.contains(pf.field) { diff --git a/lib/logstorage/pipe_fields.go b/lib/logstorage/pipe_fields.go index 1724897df..f9944432a 100644 --- a/lib/logstorage/pipe_fields.go +++ b/lib/logstorage/pipe_fields.go @@ -29,6 +29,11 @@ func (pf *pipeFields) updateNeededFields(neededFields, unneededFields fieldsSet) if pf.containsStar { return } + if neededFields.isEmpty() { + neededFields.add(pf.fields[0]) + return + } + if neededFields.contains("*") { // subtract unneeded fields from pf.fields neededFields.reset()