Added support for window clause and functions.

This commit is contained in:
go-jet 2019-09-17 13:34:47 +02:00
parent b7363a554b
commit 5ba10d35db
13 changed files with 973 additions and 48 deletions

View file

@ -85,6 +85,47 @@ var SUMi = jet.SUMi
// SUMf is aggregate function. Returns sum of float expression.
var SUMf = jet.SUMf
// -------------------- Window functions -----------------------//
// ROW_NUMBER returns number of the current row within its partition, counting from 1
var ROW_NUMBER = jet.ROW_NUMBER
// RANK of the current row with gaps; same as row_number of its first peer
var RANK = jet.RANK
// DENSE_RANK returns rank of the current row without gaps; this function counts peer groups
var DENSE_RANK = jet.DENSE_RANK
// PERCENT_RANK calculates relative rank of the current row: (rank - 1) / (total partition rows - 1)
var PERCENT_RANK = jet.PERCENT_RANK
// CUME_DIST calculates cumulative distribution: (number of partition rows preceding or peer with current row) / total partition rows
var CUME_DIST = jet.CUME_DIST
// NTILE returns integer ranging from 1 to the argument value, dividing the partition as equally as possible
var NTILE = jet.NTILE
// LAG returns value evaluated at the row that is offset rows before the current row within the partition;
// if there is no such row, instead return default (which must be of the same type as value).
// Both offset and default are evaluated with respect to the current row.
// If omitted, offset defaults to 1 and default to null
var LAG = jet.LAG
// LEAD returns value evaluated at the row that is offset rows after the current row within the partition;
// if there is no such row, instead return default (which must be of the same type as value).
// Both offset and default are evaluated with respect to the current row.
// If omitted, offset defaults to 1 and default to null
var LEAD = jet.LEAD
// FIRST_VALUE returns value evaluated at the row that is the first row of the window frame
var FIRST_VALUE = jet.FIRST_VALUE
// LAST_VALUE returns value evaluated at the row that is the last row of the window frame
var LAST_VALUE = jet.LAST_VALUE
// NTH_VALUE returns value evaluated at the row that is the nth row of the window frame (counting from 1); null if no such row
var NTH_VALUE = jet.NTH_VALUE
//--------------------- String functions ------------------//
// BIT_LENGTH returns number of bits in string expression
@ -181,7 +222,7 @@ func CURRENT_TIMESTAMP(precision ...int) TimestampExpression {
// NOW returns current datetime
func NOW(fsp ...int) DateTimeExpression {
if len(fsp) > 0 {
return jet.NewTimestampFunc("NOW", jet.ConstLiteral(int64(fsp[0])))
return jet.NewTimestampFunc("NOW", jet.FixedLiteral(int64(fsp[0])))
}
return jet.NewTimestampFunc("NOW")
}

View file

@ -1,6 +1,8 @@
package mysql
import "github.com/go-jet/jet/internal/jet"
import (
"github.com/go-jet/jet/internal/jet"
)
// RowLock is interface for SELECT statement row lock types
type RowLock = jet.RowLock
@ -11,6 +13,27 @@ var (
SHARE = jet.NewRowLock("SHARE")
)
// Window function clauses
var (
PARTITION_BY = jet.PARTITION_BY
ORDER_BY = jet.ORDER_BY
UNBOUNDED = jet.UNBOUNDED
CURRENT_ROW = jet.CURRENT_ROW
)
// PRECEDING window frame clause
func PRECEDING(offset interface{}) jet.FrameExtent {
return jet.PRECEDING(toJetFrameOffset(offset))
}
// FOLLOWING window frame clause
func FOLLOWING(offset interface{}) jet.FrameExtent {
return jet.FOLLOWING(toJetFrameOffset(offset))
}
// Window is used to specify window reference from WINDOW clause
var Window = jet.WindowName
// SelectStatement is interface for MySQL SELECT statement
type SelectStatement interface {
Statement
@ -22,6 +45,7 @@ type SelectStatement interface {
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
@ -42,7 +66,7 @@ func SELECT(projection Projection, projections ...Projection) SelectStatement {
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.OrderBy,
&newSelect.From, &newSelect.Where, &newSelect.GroupBy, &newSelect.Having, &newSelect.Window, &newSelect.OrderBy,
&newSelect.Limit, &newSelect.Offset, &newSelect.For, &newSelect.ShareLock)
newSelect.Select.Projections = toJetProjectionList(projections)
@ -66,6 +90,7 @@ type selectStatementImpl struct {
Where jet.ClauseWhere
GroupBy jet.ClauseGroupBy
Having jet.ClauseHaving
Window jet.ClauseWindow
OrderBy jet.ClauseOrderBy
Limit jet.ClauseLimit
Offset jet.ClauseOffset
@ -98,6 +123,11 @@ func (s *selectStatementImpl) HAVING(boolExpression BoolExpression) SelectStatem
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
@ -126,3 +156,31 @@ func (s *selectStatementImpl) LOCK_IN_SHARE_MODE() SelectStatement {
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 interface{}) jet.Serializer {
if offset == UNBOUNDED {
return jet.UNBOUNDED
}
// check for interval expression
//if exp, ok := offset.(Expression); ok {
// return exp
//}
return jet.FixedLiteral(offset)
}