2019-06-21 13:56:57 +02:00
|
|
|
package jet
|
2019-05-01 16:34:03 +02:00
|
|
|
|
|
|
|
|
import (
|
2019-06-05 17:15:20 +02:00
|
|
|
"errors"
|
2019-05-01 16:34:03 +02:00
|
|
|
)
|
|
|
|
|
|
2019-07-18 17:43:11 +02:00
|
|
|
// UNION effectively appends the result of sub-queries(select statements) into single query.
|
|
|
|
|
// It eliminates duplicate rows from its result.
|
2019-07-01 19:41:49 +02:00
|
|
|
func UNION(lhs, rhs SelectStatement, selects ...SelectStatement) SelectStatement {
|
|
|
|
|
return newSetStatementImpl(union, false, toSelectList(lhs, rhs, selects...))
|
2019-05-01 16:34:03 +02:00
|
|
|
}
|
|
|
|
|
|
2019-07-18 17:43:11 +02:00
|
|
|
// UNION_ALL effectively appends the result of sub-queries(select statements) into single query.
|
|
|
|
|
// It does not eliminates duplicate rows from its result.
|
2019-07-01 19:41:49 +02:00
|
|
|
func UNION_ALL(lhs, rhs SelectStatement, selects ...SelectStatement) SelectStatement {
|
|
|
|
|
return newSetStatementImpl(union, true, toSelectList(lhs, rhs, selects...))
|
2019-05-01 16:34:03 +02:00
|
|
|
}
|
|
|
|
|
|
2019-07-18 17:43:11 +02:00
|
|
|
// INTERSECT returns all rows that are in query results.
|
|
|
|
|
// It eliminates duplicate rows from its result.
|
2019-07-01 19:41:49 +02:00
|
|
|
func INTERSECT(lhs, rhs SelectStatement, selects ...SelectStatement) SelectStatement {
|
|
|
|
|
return newSetStatementImpl(intersect, false, toSelectList(lhs, rhs, selects...))
|
2019-05-01 16:34:03 +02:00
|
|
|
}
|
|
|
|
|
|
2019-07-18 17:43:11 +02:00
|
|
|
// INTERSECT_ALL returns all rows that are in query results.
|
|
|
|
|
// It does not eliminates duplicate rows from its result.
|
2019-07-01 19:41:49 +02:00
|
|
|
func INTERSECT_ALL(lhs, rhs SelectStatement, selects ...SelectStatement) SelectStatement {
|
|
|
|
|
return newSetStatementImpl(intersect, true, toSelectList(lhs, rhs, selects...))
|
2019-05-01 16:34:03 +02:00
|
|
|
}
|
|
|
|
|
|
2019-07-18 17:43:11 +02:00
|
|
|
// 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 SelectStatement) SelectStatement {
|
|
|
|
|
return newSetStatementImpl(except, false, toSelectList(lhs, rhs))
|
2019-05-01 16:34:03 +02:00
|
|
|
}
|
|
|
|
|
|
2019-07-18 17:43:11 +02:00
|
|
|
// 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 SelectStatement) SelectStatement {
|
|
|
|
|
return newSetStatementImpl(except, true, toSelectList(lhs, rhs))
|
2019-05-01 16:34:03 +02:00
|
|
|
}
|
|
|
|
|
|
2019-07-01 19:41:49 +02:00
|
|
|
func toSelectList(lhs, rhs SelectStatement, selects ...SelectStatement) []SelectStatement {
|
|
|
|
|
return append([]SelectStatement{lhs, rhs}, selects...)
|
2019-05-01 16:34:03 +02:00
|
|
|
}
|
|
|
|
|
|
2019-07-01 19:41:49 +02:00
|
|
|
const (
|
|
|
|
|
union = "UNION"
|
|
|
|
|
intersect = "INTERSECT"
|
|
|
|
|
except = "EXCEPT"
|
|
|
|
|
)
|
|
|
|
|
|
2019-05-01 16:34:03 +02:00
|
|
|
// Similar to selectStatementImpl, but less complete
|
|
|
|
|
type setStatementImpl struct {
|
2019-07-01 19:41:49 +02:00
|
|
|
selectStatementImpl
|
2019-05-05 12:37:23 +02:00
|
|
|
|
2019-07-01 19:41:49 +02:00
|
|
|
operator string
|
|
|
|
|
all bool
|
|
|
|
|
selects []SelectStatement
|
2019-05-01 16:34:03 +02:00
|
|
|
}
|
|
|
|
|
|
2019-07-01 19:41:49 +02:00
|
|
|
func newSetStatementImpl(operator string, all bool, selects []SelectStatement) SelectStatement {
|
2019-05-05 12:37:23 +02:00
|
|
|
setStatement := &setStatementImpl{
|
2019-05-01 16:34:03 +02:00
|
|
|
operator: operator,
|
|
|
|
|
all: all,
|
2019-07-01 19:41:49 +02:00
|
|
|
selects: selects,
|
2019-05-01 16:34:03 +02:00
|
|
|
}
|
2019-05-05 12:37:23 +02:00
|
|
|
|
2019-07-01 19:41:49 +02:00
|
|
|
setStatement.selectStatementImpl.expressionInterfaceImpl.parent = setStatement
|
|
|
|
|
setStatement.selectStatementImpl.parent = setStatement
|
|
|
|
|
setStatement.limit = -1
|
|
|
|
|
setStatement.offset = -1
|
2019-05-05 12:37:23 +02:00
|
|
|
|
|
|
|
|
return setStatement
|
2019-05-01 16:34:03 +02:00
|
|
|
}
|
|
|
|
|
|
2019-06-18 14:35:32 +02:00
|
|
|
func (s *setStatementImpl) projections() []projection {
|
|
|
|
|
if len(s.selects) > 0 {
|
|
|
|
|
return s.selects[0].projections()
|
|
|
|
|
}
|
|
|
|
|
return []projection{}
|
2019-05-01 16:34:03 +02:00
|
|
|
}
|
|
|
|
|
|
2019-07-08 10:48:03 +02:00
|
|
|
func (s *setStatementImpl) serialize(statement statementType, out *sqlBuilder, options ...serializeOption) error {
|
2019-05-13 12:33:11 +02:00
|
|
|
if s == nil {
|
2019-07-08 13:00:44 +02:00
|
|
|
return errors.New("jet: Set expression is nil. ")
|
2019-05-13 12:33:11 +02:00
|
|
|
}
|
2019-05-12 18:15:23 +02:00
|
|
|
|
2019-06-11 12:47:35 +02:00
|
|
|
wrap := s.orderBy != nil || s.limit >= 0 || s.offset >= 0
|
|
|
|
|
|
|
|
|
|
if wrap {
|
2019-05-08 13:47:01 +02:00
|
|
|
out.writeString("(")
|
2019-05-12 18:15:23 +02:00
|
|
|
out.increaseIdent()
|
2019-05-05 12:37:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err := s.serializeImpl(out)
|
|
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-11 12:47:35 +02:00
|
|
|
if wrap {
|
2019-05-12 18:15:23 +02:00
|
|
|
out.decreaseIdent()
|
2019-06-14 14:35:50 +02:00
|
|
|
out.newLine()
|
2019-05-08 13:47:01 +02:00
|
|
|
out.writeString(")")
|
2019-05-05 12:37:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-08 10:48:03 +02:00
|
|
|
func (s *setStatementImpl) serializeImpl(out *sqlBuilder) error {
|
2019-05-13 12:33:11 +02:00
|
|
|
if s == nil {
|
2019-07-08 13:00:44 +02:00
|
|
|
return errors.New("jet: Set expression is nil. ")
|
2019-05-13 12:33:11 +02:00
|
|
|
}
|
2019-05-03 12:51:57 +02:00
|
|
|
|
|
|
|
|
if len(s.selects) < 2 {
|
2019-07-18 17:43:11 +02:00
|
|
|
return errors.New("jet: UNION Statement must have at least two SELECT statements")
|
2019-05-01 16:34:03 +02:00
|
|
|
}
|
|
|
|
|
|
2019-06-14 14:35:50 +02:00
|
|
|
out.newLine()
|
2019-05-08 13:47:01 +02:00
|
|
|
out.writeString("(")
|
2019-05-12 18:15:23 +02:00
|
|
|
out.increaseIdent()
|
2019-05-01 16:34:03 +02:00
|
|
|
|
2019-05-03 12:51:57 +02:00
|
|
|
for i, selectStmt := range s.selects {
|
2019-06-14 14:35:50 +02:00
|
|
|
out.newLine()
|
2019-05-01 16:34:03 +02:00
|
|
|
if i > 0 {
|
2019-05-12 18:15:23 +02:00
|
|
|
out.writeString(s.operator)
|
2019-05-01 16:34:03 +02:00
|
|
|
|
2019-05-03 12:51:57 +02:00
|
|
|
if s.all {
|
2019-05-12 18:15:23 +02:00
|
|
|
out.writeString("ALL")
|
2019-05-01 16:34:03 +02:00
|
|
|
}
|
2019-06-14 14:35:50 +02:00
|
|
|
out.newLine()
|
2019-05-01 16:34:03 +02:00
|
|
|
}
|
|
|
|
|
|
2019-07-01 19:41:49 +02:00
|
|
|
if selectStmt == nil {
|
2019-07-08 13:00:44 +02:00
|
|
|
return errors.New("jet: select statement is nil")
|
2019-07-01 19:41:49 +02:00
|
|
|
}
|
|
|
|
|
|
2019-07-18 17:43:11 +02:00
|
|
|
err := selectStmt.serialize(setStatement, out)
|
2019-05-01 16:34:03 +02:00
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-12 18:15:23 +02:00
|
|
|
out.decreaseIdent()
|
2019-06-14 14:35:50 +02:00
|
|
|
out.newLine()
|
2019-05-08 13:47:01 +02:00
|
|
|
out.writeString(")")
|
2019-05-03 12:51:57 +02:00
|
|
|
|
|
|
|
|
if s.orderBy != nil {
|
2019-07-18 17:43:11 +02:00
|
|
|
err := out.writeOrderBy(setStatement, s.orderBy)
|
2019-05-03 12:51:57 +02:00
|
|
|
if err != nil {
|
2019-05-01 16:34:03 +02:00
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-03 12:51:57 +02:00
|
|
|
if s.limit >= 0 {
|
2019-06-14 14:35:50 +02:00
|
|
|
out.newLine()
|
2019-05-12 18:15:23 +02:00
|
|
|
out.writeString("LIMIT")
|
2019-07-18 17:43:11 +02:00
|
|
|
out.insertParametrizedArgument(s.limit)
|
2019-05-01 16:34:03 +02:00
|
|
|
}
|
|
|
|
|
|
2019-05-03 12:51:57 +02:00
|
|
|
if s.offset >= 0 {
|
2019-06-14 14:35:50 +02:00
|
|
|
out.newLine()
|
2019-05-12 18:15:23 +02:00
|
|
|
out.writeString("OFFSET")
|
2019-07-18 17:43:11 +02:00
|
|
|
out.insertParametrizedArgument(s.offset)
|
2019-05-01 16:34:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-18 14:35:32 +02:00
|
|
|
func (s *setStatementImpl) Sql() (query string, args []interface{}, err error) {
|
2019-07-08 10:48:03 +02:00
|
|
|
queryData := &sqlBuilder{}
|
2019-05-01 16:34:03 +02:00
|
|
|
|
2019-06-18 14:35:32 +02:00
|
|
|
err = s.serializeImpl(queryData)
|
2019-05-01 16:34:03 +02:00
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-12 18:15:23 +02:00
|
|
|
query, args = queryData.finalize()
|
|
|
|
|
return
|
|
|
|
|
}
|