console/query: SrcVlan/DstVlan as a dimension

Make the code more generic for IPv6 types and UInt types to
format them correctly.

Fix #623
This commit is contained in:
Vincent Bernat
2023-04-12 20:58:26 +02:00
parent 367e7f0036
commit b5cc995557
5 changed files with 31 additions and 9 deletions

View File

@@ -11,6 +11,10 @@ identified with a specific icon:
- 🩹: bug fix
- 🌱: miscellaneous change
## Unreleased
- 🩹 *console*: fix `SrcVlan` and `DstVlan` as a dimension
## 1.8.2 - 2023-04-08
-*orchestrator*: add an option to materialize a column instead of using an alias

View File

@@ -118,7 +118,7 @@ func (input graphLineHandlerInput) toSQL1(axis int, options toSQL1Options) strin
dimensionsInterpolate := ""
others := []string{}
for _, column := range input.Dimensions {
field := column.ToSQLSelect()
field := column.ToSQLSelect(input.schema)
selectFields = append(selectFields, field)
dimensions = append(dimensions, column.String())
others = append(others, "'Other'")

View File

@@ -7,6 +7,7 @@ package query
import (
"fmt"
"strings"
"akvorado/common/helpers"
"akvorado/common/schema"
@@ -95,11 +96,11 @@ func (qcs Columns) Validate(schema *schema.Component) error {
}
// ToSQLSelect transforms a column into an expression to use in SELECT
func (qc Column) ToSQLSelect() string {
func (qc Column) ToSQLSelect(sch *schema.Component) string {
var strValue string
switch qc.Key() {
case schema.ColumnExporterAddress, schema.ColumnSrcAddr, schema.ColumnDstAddr, schema.ColumnSrcAddrNAT, schema.ColumnDstAddrNAT:
strValue = fmt.Sprintf("replaceRegexpOne(IPv6NumToString(%s), '^::ffff:', '')", qc)
key := qc.Key()
switch key {
// Special cases
case schema.ColumnSrcAS, schema.ColumnDstAS, schema.ColumnDst1stAS, schema.ColumnDst2ndAS, schema.ColumnDst3rdAS:
strValue = fmt.Sprintf(`concat(toString(%s), ': ', dictGetOrDefault('asns', 'name', %s, '???'))`,
qc, qc)
@@ -108,16 +109,23 @@ func (qc Column) ToSQLSelect() string {
helpers.ETypeIPv4, helpers.ETypeIPv6)
case schema.ColumnProto:
strValue = `dictGetOrDefault('protocols', 'name', Proto, '???')`
case schema.ColumnInIfSpeed, schema.ColumnOutIfSpeed, schema.ColumnSrcPort, schema.ColumnDstPort, schema.ColumnForwardingStatus, schema.ColumnInIfBoundary, schema.ColumnOutIfBoundary, schema.ColumnSrcPortNAT, schema.ColumnDstPortNAT:
strValue = fmt.Sprintf("toString(%s)", qc)
case schema.ColumnDstASPath:
strValue = `arrayStringConcat(DstASPath, ' ')`
case schema.ColumnDstCommunities:
strValue = `arrayStringConcat(arrayConcat(arrayMap(c -> concat(toString(bitShiftRight(c, 16)), ':', toString(bitAnd(c, 0xffff))), DstCommunities), arrayMap(c -> concat(toString(bitAnd(bitShiftRight(c, 64), 0xffffffff)), ':', toString(bitAnd(bitShiftRight(c, 32), 0xffffffff)), ':', toString(bitAnd(c, 0xffffffff))), DstLargeCommunities)), ' ')`
case schema.ColumnSrcMAC, schema.ColumnDstMAC:
strValue = fmt.Sprintf("MACNumToString(%s)", qc)
// Generic cases
default:
strValue = qc.String()
if col, ok := sch.LookupColumnByKey(key); ok {
if strings.HasPrefix(col.ClickHouseType, "UInt") {
strValue = fmt.Sprintf(`toString(%s)`, qc)
} else if col.ClickHouseType == "IPv6" || col.ClickHouseType == "LowCardinality(IPv6)" {
strValue = fmt.Sprintf("replaceRegexpOne(IPv6NumToString(%s), '^::ffff:', '')", qc)
}
}
}
return strValue
}

View File

@@ -45,6 +45,7 @@ func TestUnmarshalQueryColumn(t *testing.T) {
}
func TestQueryColumnSQLSelect(t *testing.T) {
sch := schema.NewMock(t)
cases := []struct {
Input schema.ColumnKey
Expected string
@@ -52,6 +53,12 @@ func TestQueryColumnSQLSelect(t *testing.T) {
{
Input: schema.ColumnSrcAddr,
Expected: `replaceRegexpOne(IPv6NumToString(SrcAddr), '^::ffff:', '')`,
}, {
Input: schema.ColumnDstAddrNAT,
Expected: `replaceRegexpOne(IPv6NumToString(DstAddrNAT), '^::ffff:', '')`,
}, {
Input: schema.ColumnExporterAddress,
Expected: `replaceRegexpOne(IPv6NumToString(ExporterAddress), '^::ffff:', '')`,
}, {
Input: schema.ColumnDstAS,
Expected: `concat(toString(DstAS), ': ', dictGetOrDefault('asns', 'name', DstAS, '???'))`,
@@ -67,6 +74,9 @@ func TestQueryColumnSQLSelect(t *testing.T) {
}, {
Input: schema.ColumnOutIfSpeed,
Expected: `toString(OutIfSpeed)`,
}, {
Input: schema.ColumnDstVlan,
Expected: `toString(DstVlan)`,
}, {
Input: schema.ColumnExporterName,
Expected: `ExporterName`,
@@ -90,7 +100,7 @@ func TestQueryColumnSQLSelect(t *testing.T) {
if err := column.Validate(schema.NewMock(t).EnableAllColumns()); err != nil {
t.Fatalf("Validate() error:\n%+v", err)
}
got := column.ToSQLSelect()
got := column.ToSQLSelect(sch)
if diff := helpers.Diff(got, tc.Expected); diff != "" {
t.Errorf("toSQLWhere (-got, +want):\n%s", diff)
}

View File

@@ -46,7 +46,7 @@ func (input graphSankeyHandlerInput) toSQL() (string, error) {
arrayFields = append(arrayFields, fmt.Sprintf(`if(%s IN (SELECT %s FROM rows), %s, 'Other')`,
column.String(),
column.String(),
column.ToSQLSelect()))
column.ToSQLSelect(input.schema)))
dimensions = append(dimensions, column.String())
}
fields := []string{