@@ -51,6 +51,7 @@ type selectTranslatorVisitor struct {
5151 sp * store.Provider
5252
5353 bindings map [string ]* tableBinding
54+ autoAliasCounter int
5455 baseAlias string
5556 pendingLeftFilter []ast.Expr
5657 aggResults map [string ]string
@@ -172,6 +173,7 @@ func (v *selectTranslatorVisitor) translateSimpleSelect(stmt *ast.SelectStatemen
172173 }
173174
174175 v .bindings = make (map [string ]* tableBinding )
176+ v .autoAliasCounter = 0
175177 v .pendingLeftFilter = nil
176178 v .aggResults = nil
177179 v .baseAlias = ""
@@ -399,6 +401,11 @@ func (v *selectTranslatorVisitor) processFrom(from ast.TableExpr) ([]string, err
399401 return nil , err
400402 }
401403 return nil , nil
404+ case * ast.SubqueryTable :
405+ if err := v .registerBaseSubquery (t ); err != nil {
406+ return nil , err
407+ }
408+ return nil , nil
402409 case * ast.JoinExpr :
403410 return v .processJoin (t )
404411 default :
@@ -487,6 +494,43 @@ func (v *selectTranslatorVisitor) registerBaseTable(table *ast.TableName) error
487494 return nil
488495}
489496
497+ func (v * selectTranslatorVisitor ) registerBaseSubquery (table * ast.SubqueryTable ) error {
498+ if table == nil || table .Select == nil {
499+ return & TranslationError {
500+ Code : http .StatusBadRequest ,
501+ Message : "translator: invalid subquery reference" ,
502+ }
503+ }
504+ alias := strings .TrimSpace (table .Alias )
505+ if alias == "" {
506+ alias = v .generateSubqueryAlias ("base" )
507+ }
508+ aliasLower := strings .ToLower (alias )
509+ if v .baseAlias != "" && v .baseAlias != aliasLower {
510+ return & TranslationError {
511+ Code : http .StatusBadRequest ,
512+ Message : "translator: multiple base tables are not supported" ,
513+ }
514+ }
515+ subQuery , err := translateSelectStatementToLogsQLWithContext (table .Select , translationContext {
516+ sp : v .sp ,
517+ ctes : v .availableCTEs ,
518+ })
519+ if err != nil {
520+ return & TranslationError {
521+ Code : http .StatusBadRequest ,
522+ Message : fmt .Sprintf ("translator: failed to translate subquery: %s" , err ),
523+ Err : err ,
524+ }
525+ }
526+ v .baseAlias = aliasLower
527+ v .baseUsesPipeline = true
528+ v .basePipeline = subQuery
529+ v .baseFilter = ""
530+ v .registerBinding (aliasLower , true )
531+ return nil
532+ }
533+
490534func (v * selectTranslatorVisitor ) registerBinding (alias string , isBase bool ) {
491535 key := strings .ToLower (alias )
492536 if key == "" {
@@ -495,6 +539,21 @@ func (v *selectTranslatorVisitor) registerBinding(alias string, isBase bool) {
495539 v .bindings [key ] = & tableBinding {alias : key , isBase : isBase }
496540}
497541
542+ func (v * selectTranslatorVisitor ) generateSubqueryAlias (prefix string ) string {
543+ base := strings .TrimSpace (prefix )
544+ if base == "" {
545+ base = "subquery"
546+ }
547+ base = strings .ToLower (base )
548+ for {
549+ v .autoAliasCounter ++
550+ candidate := fmt .Sprintf ("__%s_%d" , base , v .autoAliasCounter )
551+ if _ , exists := v .bindings [candidate ]; ! exists {
552+ return candidate
553+ }
554+ }
555+ }
556+
498557func (v * selectTranslatorVisitor ) processJoin (join * ast.JoinExpr ) ([]string , error ) {
499558 if join == nil {
500559 return nil , & TranslationError {
@@ -509,16 +568,21 @@ func (v *selectTranslatorVisitor) processJoin(join *ast.JoinExpr) ([]string, err
509568 }
510569 }
511570
512- leftTable , ok := join .Left .(* ast.TableName )
513- if ! ok {
571+ switch left := join .Left .(type ) {
572+ case * ast.TableName :
573+ if err := v .registerBaseTable (left ); err != nil {
574+ return nil , err
575+ }
576+ case * ast.SubqueryTable :
577+ if err := v .registerBaseSubquery (left ); err != nil {
578+ return nil , err
579+ }
580+ default :
514581 return nil , & TranslationError {
515582 Code : http .StatusBadRequest ,
516583 Message : "translator: JOIN left side must be table reference" ,
517584 }
518585 }
519- if err := v .registerBaseTable (leftTable ); err != nil {
520- return nil , err
521- }
522586
523587 var rightAlias string
524588 var rightQuery string
@@ -606,10 +670,7 @@ func (v *selectTranslatorVisitor) processJoin(join *ast.JoinExpr) ([]string, err
606670 case * ast.SubqueryTable :
607671 alias := strings .TrimSpace (rt .Alias )
608672 if alias == "" {
609- return nil , & TranslationError {
610- Code : http .StatusBadRequest ,
611- Message : "translator: JOIN subquery requires alias" ,
612- }
673+ alias = v .generateSubqueryAlias ("join" )
613674 }
614675 rightAlias = strings .ToLower (alias )
615676 if _ , exists := v .bindings [rightAlias ]; exists {
@@ -716,8 +777,8 @@ func (v *selectTranslatorVisitor) extractJoinSpec(cond ast.JoinCondition, rightA
716777
717778 switch {
718779 case leftIsIdent && rightIsIdent :
719- leftQual := v .qualifierForIdentifier (leftIdent )
720- rightQual := v .qualifierForIdentifier (rightIdent )
780+ leftQual := v .qualifierForIdentifierWithDefault (leftIdent , v . baseAlias )
781+ rightQual := v .qualifierForIdentifierWithDefault (rightIdent , rightAlias )
721782 if leftQual == v .baseAlias && rightQual == rightAlias {
722783 leftField , err := v .normalizeIdentifier (leftIdent )
723784 if err != nil {
@@ -757,8 +818,8 @@ func (v *selectTranslatorVisitor) extractJoinSpec(cond ast.JoinCondition, rightA
757818 }
758819 }
759820
760- leftAliases := v .aliasesForExpr (bin .Left )
761- rightAliases := v .aliasesForExpr (bin .Right )
821+ leftAliases := v .aliasesForExprWithDefault (bin .Left , v . baseAlias )
822+ rightAliases := v .aliasesForExprWithDefault (bin .Right , rightAlias )
762823
763824 if v .isAliasOnly (leftAliases , v .baseAlias ) && len (rightAliases ) == 0 {
764825 leftFilters = append (leftFilters , expr )
@@ -806,22 +867,23 @@ func flattenAnd(expr ast.Expr) []ast.Expr {
806867 return []ast.Expr {expr }
807868}
808869
809- func (v * selectTranslatorVisitor ) qualifierForIdentifier (ident * ast.Identifier ) string {
870+ func (v * selectTranslatorVisitor ) qualifierForIdentifierWithDefault (ident * ast.Identifier , fallback string ) string {
810871 if ident == nil || len (ident .Parts ) == 0 {
811- return v . baseAlias
872+ return fallback
812873 }
813874 first := strings .ToLower (ident .Parts [0 ])
814875 if _ , ok := v .bindings [first ]; ok {
815876 return first
816877 }
817- return v . baseAlias
878+ return fallback
818879}
819880
820- func (v * selectTranslatorVisitor ) aliasesForExpr (expr ast.Expr ) map [string ]struct {} {
881+ func (v * selectTranslatorVisitor ) aliasesForExprWithDefault (expr ast.Expr , fallback string ) map [string ]struct {} {
821882 aliases := make (map [string ]struct {})
822883 walkExpr (expr , func (e ast.Expr ) {
823884 if id , ok := e .(* ast.Identifier ); ok {
824- aliases [v .qualifierForIdentifier (id )] = struct {}{}
885+ alias := v .qualifierForIdentifierWithDefault (id , fallback )
886+ aliases [alias ] = struct {}{}
825887 }
826888 })
827889 delete (aliases , "" )
@@ -883,7 +945,13 @@ func (v *selectTranslatorVisitor) ensureBaseAliasesOnly(expr ast.Expr) error {
883945}
884946
885947func (v * selectTranslatorVisitor ) ensureAliases (expr ast.Expr , allowed map [string ]struct {}) error {
886- aliases := v .aliasesForExpr (expr )
948+ fallback := v .baseAlias
949+ if len (allowed ) == 1 {
950+ for alias := range allowed {
951+ fallback = alias
952+ }
953+ }
954+ aliases := v .aliasesForExprWithDefault (expr , fallback )
887955 for alias := range aliases {
888956 if alias == "" {
889957 continue
0 commit comments