(name string)
| 715 | } |
| 716 | |
| 717 | func (b *sqlExprBuilder) sqlForName(name string) (expr string, unnest bool, lookup *lookupMeta, err error) { |
| 718 | // If node is nil, we are evaluating the expression against the underlying table. |
| 719 | // In this case, we only allow filters to reference dimension names. |
| 720 | if b.node == nil { |
| 721 | // First, search for the dimension in the ASTs dimension fields (this also covers any computed dimension) |
| 722 | for _, f := range b.ast.dimFields { |
| 723 | if f.Name == name { |
| 724 | // Note that we return "false" even though it may be an unnest dimension because it will already have been unnested since it's one of the dimensions included in the query. |
| 725 | // So we can filter against it as if it's a normal dimension. |
| 726 | return f.Expr, false, f.LookupMeta, nil |
| 727 | } |
| 728 | } |
| 729 | |
| 730 | // Second, search for the dimension in the metrics view's dimensions (since expressions are allowed to reference dimensions not included in the query) |
| 731 | dim, err := b.ast.LookupDimension(name, b.visible) |
| 732 | if err != nil { |
| 733 | return "", false, nil, fmt.Errorf("invalid dimension reference %q: %w", name, err) |
| 734 | } |
| 735 | |
| 736 | ex, err := b.ast.Dialect.MetricsViewDimensionExpression(dim) |
| 737 | if err != nil { |
| 738 | return "", false, nil, fmt.Errorf("invalid dimension reference %q: %w", name, err) |
| 739 | } |
| 740 | |
| 741 | var lm *lookupMeta |
| 742 | if dim.LookupTable != "" { |
| 743 | var keyExpr string |
| 744 | if dim.Column != "" { |
| 745 | keyExpr = b.ast.Dialect.EscapeIdentifier(dim.Column) |
| 746 | } else { |
| 747 | keyExpr = dim.Expression |
| 748 | } |
| 749 | lm = &lookupMeta{ |
| 750 | table: dim.LookupTable, |
| 751 | keyExpr: keyExpr, |
| 752 | keyCol: dim.LookupKeyColumn, |
| 753 | valueCol: dim.LookupValueColumn, |
| 754 | } |
| 755 | } |
| 756 | // Note: If dim.Unnest is true, we need to unnest it inside of the generated expression (because it's not part of the dimFields and therefore not unnested with a LATERAL JOIN). |
| 757 | return ex, dim.Unnest, lm, nil |
| 758 | } |
| 759 | |
| 760 | // Since node is not nil, we're in the context of a wrapped SELECT. |
| 761 | // We only allow expressions against the node's dimensions and measures (not those in scope within sub-queries). |
| 762 | |
| 763 | // Check if it's a dimension name |
| 764 | for _, f := range b.node.DimFields { |
| 765 | if f.Name == name { |
| 766 | // NOTE: We don't need to handle Unnest here because it's always applied at the innermost query (i.e. when node==nil). |
| 767 | return f.Expr, false, nil, nil |
| 768 | } |
| 769 | } |
| 770 | |
| 771 | // Can't have expressions against a measure field unless it's a pseudo-HAVING clause (pseudo because we currently output it as a WHERE in an outer SELECT) |
| 772 | if !b.pseudoHaving { |
| 773 | return "", false, nil, fmt.Errorf("name %q in expression is not a dimension available in the current context", name) |
| 774 | } |
no test coverage detected