Skip to content
This repository was archived by the owner on Nov 7, 2025. It is now read-only.

Commit cb26116

Browse files
authored
Clone full ColumnRef (#1254)
In a few places we just clone the name. It became a problem, as `top_hits' CTE` lost information somewhere about its table name and produced SQL without it.
1 parent 527ec44 commit cb26116

File tree

5 files changed

+20
-11
lines changed

5 files changed

+20
-11
lines changed

quesma/model/base_visitor.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ func (v *BaseExprVisitor) VisitColumnRef(e ColumnRef) interface{} {
7979
if v.OverrideVisitColumnRef != nil {
8080
return v.OverrideVisitColumnRef(v, e)
8181
}
82-
return NewColumnRef(e.ColumnName)
82+
return e.Clone()
8383
}
8484

8585
func (v *BaseExprVisitor) VisitNestedProperty(e NestedProperty) interface{} {

quesma/model/expr.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,18 @@ func NewColumnRef(name string) ColumnRef {
2929
return ColumnRef{ColumnName: name}
3030
}
3131

32+
func NewColumnRefWithTable(name, tableAlias string) ColumnRef {
33+
return ColumnRef{ColumnName: name, TableAlias: tableAlias}
34+
}
35+
3236
func (e ColumnRef) Accept(v ExprVisitor) interface{} {
3337
return v.VisitColumnRef(e)
3438
}
3539

40+
func (e ColumnRef) Clone() ColumnRef {
41+
return ColumnRef{TableAlias: e.TableAlias, ColumnName: e.ColumnName}
42+
}
43+
3644
// PrefixExpr represents unary operators, e.g. NOT, - etc.
3745
type PrefixExpr struct {
3846
Op string

quesma/optimize/split_time_range.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ func (s splitTimeRange) transformQuery(query *model.Query, properties map[string
243243
for i, column := range namedCTEs[0].SelectCommand.Columns {
244244
switch column := (column).(type) {
245245
case model.ColumnRef:
246-
selectedColumns[i] = model.NewColumnRef(column.ColumnName)
246+
selectedColumns[i] = column.Clone()
247247
case model.LiteralExpr:
248248
selectedColumns[i] = model.NewColumnRef(column.Value.(string))
249249
case model.AliasedExpr:

quesma/quesma/schema_transformer.go

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,7 @@ func (s *SchemaCheckPass) applyPhysicalFromExpression(currentSchema schema.Schem
411411
// TODO is this nessessery?
412412
if useCommonTable {
413413
if e.ColumnName == "timestamp" || e.ColumnName == "epoch_time" || e.ColumnName == `"epoch_time"` {
414-
return model.NewColumnRef("@timestamp")
414+
return model.NewColumnRefWithTable("@timestamp", e.TableAlias)
415415
}
416416
}
417417
return e
@@ -602,7 +602,8 @@ func (s *SchemaCheckPass) applyFullTextField(indexSchema schema.Schema, query *m
602602
var expressions []model.Expr
603603

604604
for _, field := range fullTextFields {
605-
expressions = append(expressions, model.NewInfixExpr(model.NewColumnRef(field), e.Op, e.Right))
605+
colRef := model.NewColumnRefWithTable(field, col.TableAlias)
606+
expressions = append(expressions, model.NewInfixExpr(colRef, e.Op, e.Right))
606607
}
607608

608609
res := model.Or(expressions)
@@ -644,7 +645,7 @@ func (s *SchemaCheckPass) applyTimestampField(indexSchema schema.Schema, query *
644645
timestampColumnName = *table.DiscoveredTimestampFieldName
645646
}
646647
*/
647-
var replacementExpr model.Expr
648+
var replacementName string
648649

649650
if timestampColumnName == "" {
650651
// no timestamp field found, replace with NULL if any
@@ -662,12 +663,12 @@ func (s *SchemaCheckPass) applyTimestampField(indexSchema schema.Schema, query *
662663

663664
// if the target column is not the canonical timestamp field, replace it
664665
if timestampColumnName != model.TimestampFieldName {
665-
replacementExpr = model.NewColumnRef(timestampColumnName)
666+
replacementName = timestampColumnName
666667
}
667668
}
668669

669670
// no replacement needed
670-
if replacementExpr == nil {
671+
if replacementName == "" {
671672
return query, nil
672673
}
673674

@@ -676,7 +677,7 @@ func (s *SchemaCheckPass) applyTimestampField(indexSchema schema.Schema, query *
676677

677678
// full text field should be used only in where clause
678679
if e.ColumnName == model.TimestampFieldName {
679-
return replacementExpr
680+
return model.NewColumnRefWithTable(replacementName, e.TableAlias)
680681
}
681682
return e
682683
}
@@ -713,7 +714,7 @@ func (s *SchemaCheckPass) applyFieldEncoding(indexSchema schema.Schema, query *m
713714
}
714715

715716
if resolvedField, ok := indexSchema.ResolveField(e.ColumnName); ok {
716-
return model.NewColumnRef(resolvedField.InternalPropertyName.AsString())
717+
return model.NewColumnRefWithTable(resolvedField.InternalPropertyName.AsString(), e.TableAlias)
717718
} else {
718719
if hasAttributesValuesColumn {
719720
return model.NewArrayAccess(model.NewColumnRef(clickhouse.AttributesValuesColumn), model.NewLiteral(fmt.Sprintf("'%s'", e.ColumnName)))

quesma/testdata/requests_with_special_characters.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,8 +158,8 @@ var AggregationTestsWithSpecialCharactersInFieldNames = []AggregationTestCase{
158158
"metric____quesma_total_count_col_0",
159159
"group_table"."aggr__0__key_0" AS "aggr__0__key_0",
160160
"group_table"."aggr__0__count" AS "aggr__0__count",
161-
"__bytes" AS "top_metrics__0__1_col_0",
162-
"__timestamp" AS "top_metrics__0__1_col_1",
161+
"hit_table"."__bytes" AS "top_metrics__0__1_col_0",
162+
"hit_table"."__timestamp" AS "top_metrics__0__1_col_1",
163163
ROW_NUMBER() OVER (PARTITION BY "group_table"."aggr__0__key_0" ORDER BY
164164
"__timestamp" DESC) AS "top_hits_rank"
165165
FROM quesma_top_hits_group_table AS "group_table" LEFT OUTER JOIN

0 commit comments

Comments
 (0)