From f5fae577d7fd9a0fb222a8644b727f36dd45dac7 Mon Sep 17 00:00:00 2001 From: go-jet Date: Sun, 24 May 2020 17:56:35 +0200 Subject: [PATCH] [MySQL] Add support for WITH statements and Common Table Expressions. --- mysql/functions.go | 3 +++ mysql/select_statement.go | 2 +- mysql/select_table.go | 2 +- mysql/set_statement.go | 10 +++++----- mysql/table.go | 12 ++++++------ mysql/with_statement.go | 26 ++++++++++++++++++++++++++ 6 files changed, 42 insertions(+), 13 deletions(-) create mode 100644 mysql/with_statement.go diff --git a/mysql/functions.go b/mysql/functions.go index 17702b7..1ee5a5d 100644 --- a/mysql/functions.go +++ b/mysql/functions.go @@ -85,6 +85,9 @@ var MINi = jet.MINi // MINf is aggregate function. Returns minimum value of float expression across all input values var MINf = jet.MINf +// SUM is aggregate function. Returns sum of all expressions +var SUM = jet.SUM + // SUMi is aggregate function. Returns sum of integer expression. var SUMi = jet.SUMi diff --git a/mysql/select_statement.go b/mysql/select_statement.go index 720ae57..4a7f275 100644 --- a/mysql/select_statement.go +++ b/mysql/select_statement.go @@ -69,7 +69,7 @@ func newSelectStatement(table ReadableTable, projections []Projection) SelectSta &newSelect.From, &newSelect.Where, &newSelect.GroupBy, &newSelect.Having, &newSelect.Window, &newSelect.OrderBy, &newSelect.Limit, &newSelect.Offset, &newSelect.For, &newSelect.ShareLock) - newSelect.Select.Projections = projections + newSelect.Select.ProjectionList = projections newSelect.From.Table = table newSelect.Limit.Count = -1 newSelect.Offset.Count = -1 diff --git a/mysql/select_table.go b/mysql/select_table.go index 1ac02a8..9d45ba3 100644 --- a/mysql/select_table.go +++ b/mysql/select_table.go @@ -13,7 +13,7 @@ type selectTableImpl struct { readableTableInterfaceImpl } -func newSelectTable(selectStmt jet.StatementWithProjections, alias string) SelectTable { +func newSelectTable(selectStmt jet.SerializerStatement, alias string) SelectTable { subQuery := &selectTableImpl{ SelectTable: jet.NewSelectTable(selectStmt, alias), } diff --git a/mysql/set_statement.go b/mysql/set_statement.go index ba14ece..596741d 100644 --- a/mysql/set_statement.go +++ b/mysql/set_statement.go @@ -4,13 +4,13 @@ import "github.com/go-jet/jet/internal/jet" // UNION effectively appends the result of sub-queries(select statements) into single query. // It eliminates duplicate rows from its result. -func UNION(lhs, rhs jet.StatementWithProjections, selects ...jet.StatementWithProjections) setStatement { +func UNION(lhs, rhs jet.SerializerStatement, selects ...jet.SerializerStatement) setStatement { return newSetStatementImpl(union, false, toSelectList(lhs, rhs, selects...)) } // UNION_ALL effectively appends the result of sub-queries(select statements) into single query. // It does not eliminates duplicate rows from its result. -func UNION_ALL(lhs, rhs jet.StatementWithProjections, selects ...jet.StatementWithProjections) setStatement { +func UNION_ALL(lhs, rhs jet.SerializerStatement, selects ...jet.SerializerStatement) setStatement { return newSetStatementImpl(union, true, toSelectList(lhs, rhs, selects...)) } @@ -54,7 +54,7 @@ type setStatementImpl struct { setOperator jet.ClauseSetStmtOperator } -func newSetStatementImpl(operator string, all bool, selects []jet.StatementWithProjections) setStatement { +func newSetStatementImpl(operator string, all bool, selects []jet.SerializerStatement) setStatement { newSetStatement := &setStatementImpl{} newSetStatement.ExpressionStatement = jet.NewExpressionStatementImpl(Dialect, jet.SetStatementType, newSetStatement, &newSetStatement.setOperator) @@ -93,6 +93,6 @@ const ( union = "UNION" ) -func toSelectList(lhs, rhs jet.StatementWithProjections, selects ...jet.StatementWithProjections) []jet.StatementWithProjections { - return append([]jet.StatementWithProjections{lhs, rhs}, selects...) +func toSelectList(lhs, rhs jet.SerializerStatement, selects ...jet.SerializerStatement) []jet.SerializerStatement { + return append([]jet.SerializerStatement{lhs, rhs}, selects...) } diff --git a/mysql/table.go b/mysql/table.go index 8287159..ee798e2 100644 --- a/mysql/table.go +++ b/mysql/table.go @@ -49,30 +49,30 @@ type readableTableInterfaceImpl struct { } // Generates a select query on the current tableName. -func (r *readableTableInterfaceImpl) SELECT(projection1 Projection, projections ...Projection) SelectStatement { +func (r readableTableInterfaceImpl) SELECT(projection1 Projection, projections ...Projection) SelectStatement { return newSelectStatement(r.parent, append([]Projection{projection1}, projections...)) } // Creates a inner join tableName Expression using onCondition. -func (r *readableTableInterfaceImpl) INNER_JOIN(table ReadableTable, onCondition BoolExpression) joinSelectUpdateTable { +func (r readableTableInterfaceImpl) INNER_JOIN(table ReadableTable, onCondition BoolExpression) joinSelectUpdateTable { return newJoinTable(r.parent, table, jet.InnerJoin, onCondition) } // Creates a left join tableName Expression using onCondition. -func (r *readableTableInterfaceImpl) LEFT_JOIN(table ReadableTable, onCondition BoolExpression) joinSelectUpdateTable { +func (r readableTableInterfaceImpl) LEFT_JOIN(table ReadableTable, onCondition BoolExpression) joinSelectUpdateTable { return newJoinTable(r.parent, table, jet.LeftJoin, onCondition) } // Creates a right join tableName Expression using onCondition. -func (r *readableTableInterfaceImpl) RIGHT_JOIN(table ReadableTable, onCondition BoolExpression) joinSelectUpdateTable { +func (r readableTableInterfaceImpl) RIGHT_JOIN(table ReadableTable, onCondition BoolExpression) joinSelectUpdateTable { return newJoinTable(r.parent, table, jet.RightJoin, onCondition) } -func (r *readableTableInterfaceImpl) FULL_JOIN(table ReadableTable, onCondition BoolExpression) joinSelectUpdateTable { +func (r readableTableInterfaceImpl) FULL_JOIN(table ReadableTable, onCondition BoolExpression) joinSelectUpdateTable { return newJoinTable(r.parent, table, jet.FullJoin, onCondition) } -func (r *readableTableInterfaceImpl) CROSS_JOIN(table ReadableTable) joinSelectUpdateTable { +func (r readableTableInterfaceImpl) CROSS_JOIN(table ReadableTable) joinSelectUpdateTable { return newJoinTable(r.parent, table, jet.CrossJoin, nil) } diff --git a/mysql/with_statement.go b/mysql/with_statement.go new file mode 100644 index 0000000..5991287 --- /dev/null +++ b/mysql/with_statement.go @@ -0,0 +1,26 @@ +package mysql + +import "github.com/go-jet/jet/internal/jet" + +// CommonTableExpression contains information about a CTE. +type CommonTableExpression struct { + readableTableInterfaceImpl + jet.CommonTableExpression +} + +// WITH function creates new WITH statement from list of common table expressions +func WITH(cte ...jet.CommonTableExpressionDefinition) func(statement jet.SerializerStatement) Statement { + return jet.WITH(Dialect, cte...) +} + +// CTE creates new named CommonTableExpression +func CTE(name string) CommonTableExpression { + cte := CommonTableExpression{ + readableTableInterfaceImpl: readableTableInterfaceImpl{}, + CommonTableExpression: jet.CTE(name), + } + + cte.parent = &cte + + return cte +}