jet/internal/jet/projection.go
go-jet 5cbf4aac86 Add ability to change alias of all projections in the ProjectionList.
Add ability to exclude list of columns from ProjectionList.
2022-01-05 18:00:20 +01:00

83 lines
2.6 KiB
Go

package jet
import "strings"
// Projection is interface for all projection types. Types that can be part of, for instance SELECT clause.
type Projection interface {
serializeForProjection(statement StatementType, out *SQLBuilder)
fromImpl(subQuery SelectTable) Projection
}
// SerializeForProjection is helper function for serializing projection outside of jet package
func SerializeForProjection(projection Projection, statementType StatementType, out *SQLBuilder) {
projection.serializeForProjection(statementType, out)
}
// ProjectionList is a redefined type, so that ProjectionList can be used as a Projection.
type ProjectionList []Projection
func (pl ProjectionList) fromImpl(subQuery SelectTable) Projection {
newProjectionList := ProjectionList{}
for _, projection := range pl {
newProjectionList = append(newProjectionList, projection.fromImpl(subQuery))
}
return newProjectionList
}
func (pl ProjectionList) serializeForProjection(statement StatementType, out *SQLBuilder) {
SerializeProjectionList(statement, pl, out)
}
// As will create new projection list where each column is wrapped with a new table alias.
// tableAlias should be in the form 'name' or 'name.*'.
// For instance: If projection list has a column 'Artist.Name', and tableAlias is 'Musician.*', returned projection list will
// have a column wrapped in alias 'Musician.Name'.
func (pl ProjectionList) As(tableAlias string) ProjectionList {
tableAlias = strings.TrimRight(tableAlias, ".*")
newProjectionList := ProjectionList{}
for _, projection := range pl {
switch p := projection.(type) {
case ProjectionList:
newProjectionList = append(newProjectionList, p.As(tableAlias))
case ColumnExpression:
newProjectionList = append(newProjectionList, newAlias(p, tableAlias+"."+p.Name()))
case *alias:
newAlias := *p
_, columnName := extractTableAndColumnName(newAlias.alias)
newAlias.alias = tableAlias + "." + columnName
newProjectionList = append(newProjectionList, &newAlias)
}
}
return newProjectionList
}
// Except will create new projection list in which columns contained in excluded column names are removed
func (pl ProjectionList) Except(toExclude ...Column) ProjectionList {
excludedColumnList := UnwidColumnList(toExclude)
excludedColumnNames := map[string]bool{}
for _, excludedColumn := range excludedColumnList {
excludedColumnNames[excludedColumn.Name()] = true
}
var ret ProjectionList
for _, projection := range pl {
switch p := projection.(type) {
case ProjectionList:
ret = append(ret, p.Except(toExclude...))
case ColumnExpression:
if excludedColumnNames[p.Name()] {
continue
}
ret = append(ret, p)
}
}
return ret
}