Files
akvorado/common/schema/clickhouse.go
Vincent Bernat 297e04b95c common: clickHouse → clickhouse
Let's say that we use "ClickHouse" and "clickhouse".
2024-06-09 14:59:09 +02:00

123 lines
4.4 KiB
Go

// SPDX-FileCopyrightText: 2022 Free Mobile
// SPDX-License-Identifier: AGPL-3.0-only
package schema
import (
"fmt"
"strings"
"golang.org/x/exp/slices"
)
// ClickHouseDefinition turns a column into a declaration for ClickHouse
func (column Column) ClickHouseDefinition() string {
result := []string{fmt.Sprintf("`%s`", column.Name), column.ClickHouseType}
if column.ClickHouseCodec != "" {
result = append(result, fmt.Sprintf("CODEC(%s)", column.ClickHouseCodec))
}
if column.ClickHouseAlias != "" {
result = append(result, fmt.Sprintf("ALIAS %s", column.ClickHouseAlias))
}
return strings.Join(result, " ")
}
// ClickHouseTableOption is an option to alter the values returned by ClickHouseCreateTable() and ClickHouseSelectColumns().
type ClickHouseTableOption int
const (
// ClickHouseSkipMainOnlyColumns skips the columns for the main flows table only.
ClickHouseSkipMainOnlyColumns ClickHouseTableOption = iota
// ClickHouseSkipGeneratedColumns skips the columns with a GenerateFrom value
ClickHouseSkipGeneratedColumns
// ClickHouseSkipTransformColumns skips the columns with a TransformFrom value
ClickHouseSkipTransformColumns
// ClickHouseSkipAliasedColumns skips the columns with a Alias value
ClickHouseSkipAliasedColumns
// ClickHouseSkipTimeReceived skips the time received column
ClickHouseSkipTimeReceived
// ClickHouseUseTransformFromType uses the type from TransformFrom if any
ClickHouseUseTransformFromType
// ClickHouseSubstituteGenerates changes the column name to use the default generated value
ClickHouseSubstituteGenerates
// ClickHouseSubstituteTransforms changes the column name to use the transformed value
ClickHouseSubstituteTransforms
)
// ClickHouseCreateTable returns the columns for the CREATE TABLE clause in ClickHouse.
func (schema Schema) ClickHouseCreateTable(options ...ClickHouseTableOption) string {
lines := []string{}
schema.clickhouseIterate(func(column Column) {
lines = append(lines, column.ClickHouseDefinition())
}, options...)
return strings.Join(lines, ",\n")
}
// ClickHouseSelectColumns returns the columns matching the options for use in SELECT
func (schema Schema) ClickHouseSelectColumns(options ...ClickHouseTableOption) []string {
cols := []string{}
schema.clickhouseIterate(func(column Column) {
cols = append(cols, column.Name)
}, options...)
return cols
}
func (schema Schema) clickhouseIterate(fn func(Column), options ...ClickHouseTableOption) {
for _, column := range schema.Columns() {
if slices.Contains(options, ClickHouseSkipTimeReceived) && column.Key == ColumnTimeReceived {
continue
}
if slices.Contains(options, ClickHouseSkipMainOnlyColumns) && column.ClickHouseMainOnly {
continue
}
if slices.Contains(options, ClickHouseSkipGeneratedColumns) && column.ClickHouseGenerateFrom != "" && !column.ClickHouseSelfGenerated {
continue
}
if slices.Contains(options, ClickHouseSkipTransformColumns) && column.ClickHouseTransformFrom != nil {
continue
}
if slices.Contains(options, ClickHouseSkipAliasedColumns) && column.ClickHouseAlias != "" {
continue
}
if slices.Contains(options, ClickHouseUseTransformFromType) && column.ClickHouseTransformFrom != nil {
for _, ocol := range column.ClickHouseTransformFrom {
// We assume we only need to use name/type
column.Name = ocol.Name
column.ClickHouseType = ocol.ClickHouseType
fn(column)
}
continue
}
if slices.Contains(options, ClickHouseSubstituteGenerates) && column.ClickHouseGenerateFrom != "" {
column.Name = fmt.Sprintf("%s AS %s", column.ClickHouseGenerateFrom, column.Name)
}
if slices.Contains(options, ClickHouseSubstituteTransforms) && column.ClickHouseTransformFrom != nil {
column.Name = fmt.Sprintf("%s AS %s", column.ClickHouseTransformTo, column.Name)
}
fn(column)
}
}
// ClickHouseSortingKeys returns the list of sorting keys, prefixed by the primary keys.
func (schema Schema) ClickHouseSortingKeys() []string {
cols := schema.ClickHousePrimaryKeys()
for _, column := range schema.Columns() {
if column.ClickHouseNotSortingKey || column.ClickHouseMainOnly {
continue
}
if !slices.Contains(cols, column.Name) {
cols = append(cols, column.Name)
}
}
return cols
}
// ClickHousePrimaryKeys returns the list of primary keys.
func (schema Schema) ClickHousePrimaryKeys() []string {
cols := []string{}
for _, key := range schema.clickhousePrimaryKeys {
cols = append(cols, key.String())
}
return cols
}