diff --git a/postgres/clause.go b/postgres/clause.go index ad61b9a..3812667 100644 --- a/postgres/clause.go +++ b/postgres/clause.go @@ -5,18 +5,23 @@ import ( ) type clauseReturning struct { - Projections []jet.Projection + ProjectionList []jet.Projection } func (r *clauseReturning) Serialize(statementType jet.StatementType, out *jet.SQLBuilder, options ...jet.SerializeOption) { - if len(r.Projections) == 0 { + if len(r.ProjectionList) == 0 { return } out.NewLine() out.WriteString("RETURNING") out.IncreaseIdent() - out.WriteProjections(statementType, r.Projections) + out.WriteProjections(statementType, r.ProjectionList) + out.DecreaseIdent() +} + +func (r clauseReturning) Projections() ProjectionList { + return r.ProjectionList } // ========================================== // diff --git a/postgres/delete_statement.go b/postgres/delete_statement.go index b39b7c1..ff62710 100644 --- a/postgres/delete_statement.go +++ b/postgres/delete_statement.go @@ -4,7 +4,7 @@ import "github.com/go-jet/jet/internal/jet" // DeleteStatement is interface for PostgreSQL DELETE statement type DeleteStatement interface { - Statement + jet.SerializerStatement WHERE(expression BoolExpression) DeleteStatement @@ -37,6 +37,6 @@ func (d *deleteStatementImpl) WHERE(expression BoolExpression) DeleteStatement { } func (d *deleteStatementImpl) RETURNING(projections ...jet.Projection) DeleteStatement { - d.Returning.Projections = projections + d.Returning.ProjectionList = projections return d } diff --git a/postgres/functions.go b/postgres/functions.go index ddd01db..b97d25a 100644 --- a/postgres/functions.go +++ b/postgres/functions.go @@ -87,6 +87,9 @@ var MINf = jet.MINf // MINi is aggregate function. Returns minimum value of int expression across all input values var MINi = jet.MINi +// SUM is aggregate function. Returns sum of all expressions +var SUM = jet.SUM + // SUMf is aggregate function. Returns sum of expression across all float expressions var SUMf = jet.SUMf diff --git a/postgres/insert_statement.go b/postgres/insert_statement.go index e4c72f5..da13370 100644 --- a/postgres/insert_statement.go +++ b/postgres/insert_statement.go @@ -4,7 +4,7 @@ import "github.com/go-jet/jet/internal/jet" // InsertStatement is interface for SQL INSERT statements type InsertStatement interface { - Statement + jet.SerializerStatement // Insert row of values VALUES(value interface{}, values ...interface{}) InsertStatement @@ -55,7 +55,7 @@ func (i *insertStatementImpl) MODELS(data interface{}) InsertStatement { } func (i *insertStatementImpl) RETURNING(projections ...jet.Projection) InsertStatement { - i.Returning.Projections = projections + i.Returning.ProjectionList = projections return i } diff --git a/postgres/select_statement.go b/postgres/select_statement.go index c001a57..3e49534 100644 --- a/postgres/select_statement.go +++ b/postgres/select_statement.go @@ -75,7 +75,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.Select.Projections = projections + newSelect.Select.ProjectionList = projections newSelect.From.Table = table newSelect.Limit.Count = -1 newSelect.Offset.Count = -1 diff --git a/postgres/select_table.go b/postgres/select_table.go index 8dea4cc..fe96bbe 100644 --- a/postgres/select_table.go +++ b/postgres/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/postgres/set_statement.go b/postgres/set_statement.go index cc6d1fe..4c83ecf 100644 --- a/postgres/set_statement.go +++ b/postgres/set_statement.go @@ -4,37 +4,37 @@ 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...)) } // INTERSECT returns all rows that are in query results. // It eliminates duplicate rows from its result. -func INTERSECT(lhs, rhs jet.StatementWithProjections, selects ...jet.StatementWithProjections) setStatement { +func INTERSECT(lhs, rhs jet.SerializerStatement, selects ...jet.SerializerStatement) setStatement { return newSetStatementImpl(intersect, false, toSelectList(lhs, rhs, selects...)) } // INTERSECT_ALL returns all rows that are in query results. // It does not eliminates duplicate rows from its result. -func INTERSECT_ALL(lhs, rhs jet.StatementWithProjections, selects ...jet.StatementWithProjections) setStatement { +func INTERSECT_ALL(lhs, rhs jet.SerializerStatement, selects ...jet.SerializerStatement) setStatement { return newSetStatementImpl(intersect, true, toSelectList(lhs, rhs, selects...)) } // EXCEPT returns all rows that are in the result of query lhs but not in the result of query rhs. // It eliminates duplicate rows from its result. -func EXCEPT(lhs, rhs jet.StatementWithProjections) setStatement { +func EXCEPT(lhs, rhs jet.SerializerStatement) setStatement { return newSetStatementImpl(except, false, toSelectList(lhs, rhs)) } // EXCEPT_ALL returns all rows that are in the result of query lhs but not in the result of query rhs. // It does not eliminates duplicate rows from its result. -func EXCEPT_ALL(lhs, rhs jet.StatementWithProjections) setStatement { +func EXCEPT_ALL(lhs, rhs jet.SerializerStatement) setStatement { return newSetStatementImpl(except, true, toSelectList(lhs, rhs)) } @@ -98,7 +98,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) @@ -139,6 +139,6 @@ const ( except = "EXCEPT" ) -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/postgres/table.go b/postgres/table.go index c82a8f7..e928004 100644 --- a/postgres/table.go +++ b/postgres/table.go @@ -54,30 +54,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) ReadableTable { +func (r readableTableInterfaceImpl) INNER_JOIN(table ReadableTable, onCondition BoolExpression) ReadableTable { 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) ReadableTable { +func (r readableTableInterfaceImpl) LEFT_JOIN(table ReadableTable, onCondition BoolExpression) ReadableTable { 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) ReadableTable { +func (r readableTableInterfaceImpl) RIGHT_JOIN(table ReadableTable, onCondition BoolExpression) ReadableTable { return newJoinTable(r.parent, table, jet.RightJoin, onCondition) } -func (r *readableTableInterfaceImpl) FULL_JOIN(table ReadableTable, onCondition BoolExpression) ReadableTable { +func (r readableTableInterfaceImpl) FULL_JOIN(table ReadableTable, onCondition BoolExpression) ReadableTable { return newJoinTable(r.parent, table, jet.FullJoin, onCondition) } -func (r *readableTableInterfaceImpl) CROSS_JOIN(table ReadableTable) ReadableTable { +func (r readableTableInterfaceImpl) CROSS_JOIN(table ReadableTable) ReadableTable { return newJoinTable(r.parent, table, jet.CrossJoin, nil) } diff --git a/postgres/update_statement.go b/postgres/update_statement.go index 9c56012..29fd9c8 100644 --- a/postgres/update_statement.go +++ b/postgres/update_statement.go @@ -6,7 +6,7 @@ import ( // UpdateStatement is interface of SQL UPDATE statement type UpdateStatement interface { - Statement + jet.SerializerStatement SET(value interface{}, values ...interface{}) UpdateStatement MODEL(data interface{}) UpdateStatement @@ -67,7 +67,7 @@ func (u *updateStatementImpl) WHERE(expression BoolExpression) UpdateStatement { } func (u *updateStatementImpl) RETURNING(projections ...jet.Projection) UpdateStatement { - u.Returning.Projections = projections + u.Returning.ProjectionList = projections return u } diff --git a/postgres/with_statement.go b/postgres/with_statement.go new file mode 100644 index 0000000..caa7100 --- /dev/null +++ b/postgres/with_statement.go @@ -0,0 +1,26 @@ +package postgres + +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 +}