jet/postgres/select_statement.go
2020-06-27 18:48:19 +02:00

178 lines
4.7 KiB
Go

package postgres
import (
"github.com/go-jet/jet/v2/internal/jet"
"math"
)
// RowLock is interface for SELECT statement row lock types
type RowLock = jet.RowLock
// Row lock types
var (
UPDATE = jet.NewRowLock("UPDATE")
NO_KEY_UPDATE = jet.NewRowLock("NO KEY UPDATE")
SHARE = jet.NewRowLock("SHARE")
KEY_SHARE = jet.NewRowLock("KEY SHARE")
)
// Window function clauses
var (
PARTITION_BY = jet.PARTITION_BY
ORDER_BY = jet.ORDER_BY
UNBOUNDED = int64(math.MaxInt64)
CURRENT_ROW = jet.CURRENT_ROW
)
// PRECEDING window frame clause
func PRECEDING(offset int64) jet.FrameExtent {
return jet.PRECEDING(toJetFrameOffset(offset))
}
// FOLLOWING window frame clause
func FOLLOWING(offset int64) jet.FrameExtent {
return jet.FOLLOWING(toJetFrameOffset(offset))
}
// Window definition reference
var Window = jet.WindowName
// SelectStatement is interface for PostgreSQL SELECT statement
type SelectStatement interface {
Statement
jet.HasProjections
Expression
DISTINCT() SelectStatement
FROM(table ReadableTable) SelectStatement
WHERE(expression BoolExpression) SelectStatement
GROUP_BY(groupByClauses ...jet.GroupByClause) SelectStatement
HAVING(boolExpression BoolExpression) SelectStatement
WINDOW(name string) windowExpand
ORDER_BY(orderByClauses ...jet.OrderByClause) SelectStatement
LIMIT(limit int64) SelectStatement
OFFSET(offset int64) SelectStatement
FOR(lock RowLock) SelectStatement
UNION(rhs SelectStatement) setStatement
UNION_ALL(rhs SelectStatement) setStatement
INTERSECT(rhs SelectStatement) setStatement
INTERSECT_ALL(rhs SelectStatement) setStatement
EXCEPT(rhs SelectStatement) setStatement
EXCEPT_ALL(rhs SelectStatement) setStatement
AsTable(alias string) SelectTable
}
//SELECT creates new SelectStatement with list of projections
func SELECT(projection Projection, projections ...Projection) SelectStatement {
return newSelectStatement(nil, append([]Projection{projection}, projections...))
}
func newSelectStatement(table ReadableTable, projections []Projection) SelectStatement {
newSelect := &selectStatementImpl{}
newSelect.ExpressionStatement = jet.NewExpressionStatementImpl(Dialect, jet.SelectStatementType, newSelect, &newSelect.Select,
&newSelect.From, &newSelect.Where, &newSelect.GroupBy, &newSelect.Having, &newSelect.Window, &newSelect.OrderBy,
&newSelect.Limit, &newSelect.Offset, &newSelect.For)
newSelect.Select.ProjectionList = projections
newSelect.From.Table = table
newSelect.Limit.Count = -1
newSelect.Offset.Count = -1
newSelect.setOperatorsImpl.parent = newSelect
return newSelect
}
type selectStatementImpl struct {
jet.ExpressionStatement
setOperatorsImpl
Select jet.ClauseSelect
From jet.ClauseFrom
Where jet.ClauseWhere
GroupBy jet.ClauseGroupBy
Having jet.ClauseHaving
Window jet.ClauseWindow
OrderBy jet.ClauseOrderBy
Limit jet.ClauseLimit
Offset jet.ClauseOffset
For jet.ClauseFor
}
func (s *selectStatementImpl) DISTINCT() SelectStatement {
s.Select.Distinct = true
return s
}
func (s *selectStatementImpl) FROM(table ReadableTable) SelectStatement {
s.From.Table = table
return s
}
func (s *selectStatementImpl) WHERE(condition BoolExpression) SelectStatement {
s.Where.Condition = condition
return s
}
func (s *selectStatementImpl) GROUP_BY(groupByClauses ...jet.GroupByClause) SelectStatement {
s.GroupBy.List = groupByClauses
return s
}
func (s *selectStatementImpl) HAVING(boolExpression BoolExpression) SelectStatement {
s.Having.Condition = boolExpression
return s
}
func (s *selectStatementImpl) WINDOW(name string) windowExpand {
s.Window.Definitions = append(s.Window.Definitions, jet.WindowDefinition{Name: name})
return windowExpand{selectStatement: s}
}
func (s *selectStatementImpl) ORDER_BY(orderByClauses ...jet.OrderByClause) SelectStatement {
s.OrderBy.List = orderByClauses
return s
}
func (s *selectStatementImpl) LIMIT(limit int64) SelectStatement {
s.Limit.Count = limit
return s
}
func (s *selectStatementImpl) OFFSET(offset int64) SelectStatement {
s.Offset.Count = offset
return s
}
func (s *selectStatementImpl) FOR(lock RowLock) SelectStatement {
s.For.Lock = lock
return s
}
func (s *selectStatementImpl) AsTable(alias string) SelectTable {
return newSelectTable(s, alias)
}
//-----------------------------------------------------
type windowExpand struct {
selectStatement *selectStatementImpl
}
func (w windowExpand) AS(window ...jet.Window) SelectStatement {
if len(window) == 0 {
return w.selectStatement
}
windowsDefinition := w.selectStatement.Window.Definitions
windowsDefinition[len(windowsDefinition)-1].Window = window[0]
return w.selectStatement
}
func toJetFrameOffset(offset int64) jet.Serializer {
if offset == UNBOUNDED {
return jet.UNBOUNDED
}
return jet.FixedLiteral(offset)
}