jet/postgres/select_statement.go

238 lines
6 KiB
Go
Raw Permalink Normal View History

2019-08-11 09:52:02 +02:00
package postgres
import (
"math"
"source.gleipnir.technology/Gleipnir/jet/v2/internal/jet"
)
2019-08-11 09:52:02 +02:00
2019-08-17 14:49:35 +02:00
// RowLock is interface for SELECT statement row lock types
2019-08-17 10:43:16 +02:00
type RowLock = jet.RowLock
2019-08-11 09:52:02 +02:00
2019-08-17 14:49:35 +02:00
// Row lock types
2019-08-11 09:52:02 +02:00
var (
2019-08-17 18:32:01 +02:00
UPDATE = jet.NewRowLock("UPDATE")
NO_KEY_UPDATE = jet.NewRowLock("NO KEY UPDATE")
SHARE = jet.NewRowLock("SHARE")
KEY_SHARE = jet.NewRowLock("KEY SHARE")
2019-08-11 09:52:02 +02:00
)
// 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
2019-08-17 14:49:35 +02:00
// SelectStatement is interface for PostgreSQL SELECT statement
2019-08-11 09:52:02 +02:00
type SelectStatement interface {
2019-08-17 10:43:16 +02:00
Statement
2019-08-11 09:52:02 +02:00
jet.HasProjections
2019-08-17 10:43:16 +02:00
Expression
2019-08-11 09:52:02 +02:00
DISTINCT(on ...jet.ColumnExpression) SelectStatement
2021-05-03 18:48:15 +02:00
FROM(tables ...ReadableTable) SelectStatement
2019-08-11 09:52:02 +02:00
WHERE(expression BoolExpression) SelectStatement
GROUP_BY(groupByClauses ...GroupByClause) SelectStatement
2019-08-11 09:52:02 +02:00
HAVING(boolExpression BoolExpression) SelectStatement
WINDOW(name string) windowExpand
ORDER_BY(orderByClauses ...OrderByClause) SelectStatement
2019-08-11 09:52:02 +02:00
LIMIT(limit int64) SelectStatement
OFFSET(offset int64) SelectStatement
// OFFSET_e can be used when an integer expression is needed as offset, otherwise OFFSET can be used
OFFSET_e(offset IntegerExpression) SelectStatement
2024-02-07 11:07:50 +01:00
FETCH_FIRST(count IntegerExpression) fetchExpand
2019-08-17 10:43:16 +02:00
FOR(lock RowLock) SelectStatement
2019-08-11 09:52:02 +02:00
2019-08-17 10:43:16 +02:00
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
2019-08-11 09:52:02 +02:00
AsTable(alias string) SelectTable
}
2022-08-23 12:38:16 +02:00
// SELECT creates new SelectStatement with list of projections
2019-08-16 11:19:06 +02:00
func SELECT(projection Projection, projections ...Projection) SelectStatement {
return newSelectStatement(jet.SelectStatementType, nil, append([]Projection{projection}, projections...))
2019-08-11 09:52:02 +02:00
}
func newSelectStatement(stmtType jet.StatementType, table ReadableTable, projections []Projection) *selectStatementImpl {
2019-08-11 09:52:02 +02:00
newSelect := &selectStatementImpl{}
newSelect.ExpressionStatement = jet.NewExpressionStatementImpl(Dialect, stmtType, newSelect,
2024-02-07 11:07:50 +01:00
&newSelect.Select,
&newSelect.From,
&newSelect.Where,
&newSelect.GroupBy,
&newSelect.Having,
&newSelect.Window,
&newSelect.OrderBy,
&newSelect.Limit,
&newSelect.Offset,
&newSelect.Fetch,
&newSelect.For)
2019-08-11 09:52:02 +02:00
newSelect.Select.ProjectionList = projections
2021-05-03 18:48:15 +02:00
if table != nil {
newSelect.From.Tables = []jet.Serializer{table}
}
2019-08-11 09:52:02 +02:00
newSelect.Limit.Count = -1
newSelect.setOperatorsImpl.stmtRoot = newSelect
2019-08-11 09:52:02 +02:00
return newSelect
}
type selectStatementImpl struct {
2019-08-17 18:32:01 +02:00
jet.ExpressionStatement
2019-08-11 09:52:02 +02:00
setOperatorsImpl
Select jet.ClauseSelect
From jet.ClauseFrom
Where jet.ClauseWhere
GroupBy jet.ClauseGroupBy
Having jet.ClauseHaving
Window jet.ClauseWindow
2019-08-11 09:52:02 +02:00
OrderBy jet.ClauseOrderBy
Limit jet.ClauseLimit
Offset jet.ClauseOffset
2024-02-07 11:07:50 +01:00
Fetch jet.ClauseFetch
2019-08-11 09:52:02 +02:00
For jet.ClauseFor
}
func (s *selectStatementImpl) DISTINCT(on ...jet.ColumnExpression) SelectStatement {
2019-08-11 09:52:02 +02:00
s.Select.Distinct = true
s.Select.DistinctOnColumns = on
2019-08-11 09:52:02 +02:00
return s
}
2021-05-03 18:48:15 +02:00
func (s *selectStatementImpl) FROM(tables ...ReadableTable) SelectStatement {
s.From.Tables = readableTablesToSerializerList(tables)
2019-08-11 09:52:02 +02:00
return s
}
func (s *selectStatementImpl) WHERE(condition BoolExpression) SelectStatement {
s.Where.Condition = condition
return s
}
func (s *selectStatementImpl) GROUP_BY(groupByClauses ...GroupByClause) SelectStatement {
2019-08-11 09:52:02 +02:00
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,
rootStmt: s,
}
}
func (s *selectStatementImpl) ORDER_BY(orderByClauses ...OrderByClause) SelectStatement {
2019-08-11 09:52:02 +02:00
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 = Int(offset)
return s
}
func (s *selectStatementImpl) OFFSET_e(offset IntegerExpression) SelectStatement {
2019-08-11 09:52:02 +02:00
s.Offset.Count = offset
return s
}
2024-02-07 11:07:50 +01:00
func (s *selectStatementImpl) FETCH_FIRST(count IntegerExpression) fetchExpand {
s.Fetch.Count = count
return fetchExpand{
selectStatement: s,
rootStmt: s,
2024-02-07 11:07:50 +01:00
}
}
2019-08-17 10:43:16 +02:00
func (s *selectStatementImpl) FOR(lock RowLock) SelectStatement {
2019-08-11 09:52:02 +02:00
s.For.Lock = lock
return s
}
func (s *selectStatementImpl) AsTable(alias string) SelectTable {
2024-10-17 14:12:21 +02:00
return newSelectTable(s, alias, nil)
2019-08-11 09:52:02 +02:00
}
//-----------------------------------------------------
type windowExpand struct {
selectStatement *selectStatementImpl
rootStmt SelectStatement
}
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.rootStmt
}
func toJetFrameOffset(offset int64) jet.Serializer {
if offset == UNBOUNDED {
return jet.UNBOUNDED
}
return jet.FixedLiteral(offset)
}
func readableTablesToSerializerList(tables []ReadableTable) []jet.Serializer {
var ret []jet.Serializer
for _, table := range tables {
ret = append(ret, table)
}
return ret
}
2024-02-07 11:07:50 +01:00
type fetchExpand struct {
selectStatement *selectStatementImpl
rootStmt SelectStatement
2024-02-07 11:07:50 +01:00
}
func (f fetchExpand) ROWS_ONLY() SelectStatement {
f.selectStatement.Fetch.WithTies = false
return f.rootStmt
2024-02-07 11:07:50 +01:00
}
func (f fetchExpand) ROWS_WITH_TIES() SelectStatement {
f.selectStatement.Fetch.WithTies = true
return f.rootStmt
2024-02-07 11:07:50 +01:00
}