Handle unsupported set operators for MySQL.
This commit is contained in:
parent
4c5584aaae
commit
7930fb23ba
4 changed files with 133 additions and 13 deletions
|
|
@ -7,37 +7,37 @@ import (
|
||||||
// UNION effectively appends the result of sub-queries(select statements) into single query.
|
// UNION effectively appends the result of sub-queries(select statements) into single query.
|
||||||
// It eliminates duplicate rows from its result.
|
// It eliminates duplicate rows from its result.
|
||||||
func UNION(lhs, rhs SelectStatement, selects ...SelectStatement) SelectStatement {
|
func UNION(lhs, rhs SelectStatement, selects ...SelectStatement) SelectStatement {
|
||||||
return newSetStatementImpl(union, false, toSelectList(lhs, rhs, selects...))
|
return newSetStatementImpl(Union, false, toSelectList(lhs, rhs, selects...))
|
||||||
}
|
}
|
||||||
|
|
||||||
// UNION_ALL effectively appends the result of sub-queries(select statements) into single query.
|
// UNION_ALL effectively appends the result of sub-queries(select statements) into single query.
|
||||||
// It does not eliminates duplicate rows from its result.
|
// It does not eliminates duplicate rows from its result.
|
||||||
func UNION_ALL(lhs, rhs SelectStatement, selects ...SelectStatement) SelectStatement {
|
func UNION_ALL(lhs, rhs SelectStatement, selects ...SelectStatement) SelectStatement {
|
||||||
return newSetStatementImpl(union, true, toSelectList(lhs, rhs, selects...))
|
return newSetStatementImpl(Union, true, toSelectList(lhs, rhs, selects...))
|
||||||
}
|
}
|
||||||
|
|
||||||
// INTERSECT returns all rows that are in query results.
|
// INTERSECT returns all rows that are in query results.
|
||||||
// It eliminates duplicate rows from its result.
|
// It eliminates duplicate rows from its result.
|
||||||
func INTERSECT(lhs, rhs SelectStatement, selects ...SelectStatement) SelectStatement {
|
func INTERSECT(lhs, rhs SelectStatement, selects ...SelectStatement) SelectStatement {
|
||||||
return newSetStatementImpl(intersect, false, toSelectList(lhs, rhs, selects...))
|
return newSetStatementImpl(Intersect, false, toSelectList(lhs, rhs, selects...))
|
||||||
}
|
}
|
||||||
|
|
||||||
// INTERSECT_ALL returns all rows that are in query results.
|
// INTERSECT_ALL returns all rows that are in query results.
|
||||||
// It does not eliminates duplicate rows from its result.
|
// It does not eliminates duplicate rows from its result.
|
||||||
func INTERSECT_ALL(lhs, rhs SelectStatement, selects ...SelectStatement) SelectStatement {
|
func INTERSECT_ALL(lhs, rhs SelectStatement, selects ...SelectStatement) SelectStatement {
|
||||||
return newSetStatementImpl(intersect, true, toSelectList(lhs, rhs, selects...))
|
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.
|
// 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.
|
// It eliminates duplicate rows from its result.
|
||||||
func EXCEPT(lhs, rhs SelectStatement) SelectStatement {
|
func EXCEPT(lhs, rhs SelectStatement) SelectStatement {
|
||||||
return newSetStatementImpl(except, false, toSelectList(lhs, rhs))
|
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.
|
// 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.
|
// It does not eliminates duplicate rows from its result.
|
||||||
func EXCEPT_ALL(lhs, rhs SelectStatement) SelectStatement {
|
func EXCEPT_ALL(lhs, rhs SelectStatement) SelectStatement {
|
||||||
return newSetStatementImpl(except, true, toSelectList(lhs, rhs))
|
return newSetStatementImpl(Except, true, toSelectList(lhs, rhs))
|
||||||
}
|
}
|
||||||
|
|
||||||
func toSelectList(lhs, rhs SelectStatement, selects ...SelectStatement) []SelectStatement {
|
func toSelectList(lhs, rhs SelectStatement, selects ...SelectStatement) []SelectStatement {
|
||||||
|
|
@ -45,9 +45,9 @@ func toSelectList(lhs, rhs SelectStatement, selects ...SelectStatement) []Select
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
union = "UNION"
|
Union = "UNION"
|
||||||
intersect = "INTERSECT"
|
Intersect = "INTERSECT"
|
||||||
except = "EXCEPT"
|
Except = "EXCEPT"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Similar to selectStatementImpl, but less complete
|
// Similar to selectStatementImpl, but less complete
|
||||||
|
|
@ -125,6 +125,10 @@ func (s *setStatementImpl) serializeImpl(out *SqlBuilder) error {
|
||||||
return errors.New("jet: UNION Statement must have at least two SELECT statements")
|
return errors.New("jet: UNION Statement must have at least two SELECT statements")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if setOverride := out.Dialect.SerializeOverride(s.operator); setOverride != nil {
|
||||||
|
return setOverride()(SelectStatementType, out)
|
||||||
|
}
|
||||||
|
|
||||||
out.newLine()
|
out.newLine()
|
||||||
out.WriteString("(")
|
out.WriteString("(")
|
||||||
out.increaseIdent()
|
out.increaseIdent()
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,8 @@ func NewDialect() jet.Dialect {
|
||||||
serializeOverrides["/"] = mysql_DIVISION
|
serializeOverrides["/"] = mysql_DIVISION
|
||||||
serializeOverrides["#"] = mysql_BIT_XOR
|
serializeOverrides["#"] = mysql_BIT_XOR
|
||||||
serializeOverrides[jet.StringConcatOperator] = mysql_CONCAT_operator
|
serializeOverrides[jet.StringConcatOperator] = mysql_CONCAT_operator
|
||||||
|
serializeOverrides[jet.Except] = mysql_EXCEPT
|
||||||
|
serializeOverrides[jet.Intersect] = mysql_INTERSECT
|
||||||
|
|
||||||
mySQLDialectParams := jet.DialectParams{
|
mySQLDialectParams := jet.DialectParams{
|
||||||
Name: "MySQL",
|
Name: "MySQL",
|
||||||
|
|
@ -31,6 +33,18 @@ func NewDialect() jet.Dialect {
|
||||||
return jet.NewDialect(mySQLDialectParams)
|
return jet.NewDialect(mySQLDialectParams)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func mysql_EXCEPT(expressions ...jet.Expression) jet.SerializeFunc {
|
||||||
|
return func(statement jet.StatementType, out *jet.SqlBuilder, options ...jet.SerializeOption) error {
|
||||||
|
panic("jet: MySQL does not support EXCEPT operator.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func mysql_INTERSECT(expressions ...jet.Expression) jet.SerializeFunc {
|
||||||
|
return func(statement jet.StatementType, out *jet.SqlBuilder, options ...jet.SerializeOption) error {
|
||||||
|
panic("jet: MySQL does not support INTERSECT operator.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func mysql_BIT_XOR(expressions ...jet.Expression) jet.SerializeFunc {
|
func mysql_BIT_XOR(expressions ...jet.Expression) jet.SerializeFunc {
|
||||||
return func(statement jet.StatementType, out *jet.SqlBuilder, options ...jet.SerializeOption) error {
|
return func(statement jet.StatementType, out *jet.SqlBuilder, options ...jet.SerializeOption) error {
|
||||||
if len(expressions) != 2 {
|
if len(expressions) != 2 {
|
||||||
|
|
|
||||||
|
|
@ -15,10 +15,6 @@ var (
|
||||||
|
|
||||||
var UNION = jet.UNION
|
var UNION = jet.UNION
|
||||||
var UNION_ALL = jet.UNION_ALL
|
var UNION_ALL = jet.UNION_ALL
|
||||||
var INTERSECT = jet.INTERSECT
|
|
||||||
var INTERSECT_ALL = jet.INTERSECT_ALL
|
|
||||||
var EXCEPT = jet.EXCEPT
|
|
||||||
var EXCEPT_ALL = jet.EXCEPT_ALL
|
|
||||||
|
|
||||||
//-----------------literals----------------------//
|
//-----------------literals----------------------//
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -215,6 +215,112 @@ LIMIT ?;
|
||||||
LIMIT(12)
|
LIMIT(12)
|
||||||
|
|
||||||
testutils.AssertStatementSql(t, query, expectedSQL, int64(1), int64(1), int64(10), int64(1), int64(2), int64(1), int64(12))
|
testutils.AssertStatementSql(t, query, expectedSQL, int64(1), int64(1), int64(10), int64(1), int64(2), int64(1), int64(12))
|
||||||
|
|
||||||
|
err := query.Query(db, &struct{}{})
|
||||||
|
assert.NilError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSelectUNION(t *testing.T) {
|
||||||
|
expectedSQL := `
|
||||||
|
(
|
||||||
|
(
|
||||||
|
SELECT payment.payment_id AS "payment.payment_id"
|
||||||
|
FROM dvds.payment
|
||||||
|
LIMIT ?
|
||||||
|
OFFSET ?
|
||||||
|
)
|
||||||
|
UNION
|
||||||
|
(
|
||||||
|
SELECT payment.payment_id AS "payment.payment_id"
|
||||||
|
FROM dvds.payment
|
||||||
|
LIMIT ?
|
||||||
|
OFFSET ?
|
||||||
|
)
|
||||||
|
)
|
||||||
|
LIMIT ?;
|
||||||
|
`
|
||||||
|
query := UNION(
|
||||||
|
Payment.SELECT(Payment.PaymentID).LIMIT(1).OFFSET(10),
|
||||||
|
Payment.SELECT(Payment.PaymentID).LIMIT(1).OFFSET(2),
|
||||||
|
).LIMIT(1)
|
||||||
|
|
||||||
|
//fmt.Println(query.Sql())
|
||||||
|
|
||||||
|
testutils.AssertStatementSql(t, query, expectedSQL, int64(1), int64(10), int64(1), int64(2), int64(1))
|
||||||
|
|
||||||
|
query2 := Payment.SELECT(Payment.PaymentID).LIMIT(1).OFFSET(10).
|
||||||
|
UNION(Payment.SELECT(Payment.PaymentID).LIMIT(1).OFFSET(2)).LIMIT(1)
|
||||||
|
|
||||||
|
testutils.AssertStatementSql(t, query2, expectedSQL, int64(1), int64(10), int64(1), int64(2), int64(1))
|
||||||
|
|
||||||
|
err := query.Query(db, &struct{}{})
|
||||||
|
assert.NilError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSelectINTERSECT(t *testing.T) {
|
||||||
|
defer func() {
|
||||||
|
r := recover()
|
||||||
|
assert.Equal(t, r, "jet: MySQL does not support INTERSECT operator.")
|
||||||
|
}()
|
||||||
|
|
||||||
|
query := Payment.SELECT(Payment.PaymentID).LIMIT(1).OFFSET(10).
|
||||||
|
INTERSECT(Payment.SELECT(Payment.PaymentID).LIMIT(1).OFFSET(2)).LIMIT(1)
|
||||||
|
|
||||||
|
//fmt.Println(query.DebugSql())
|
||||||
|
|
||||||
|
err := query.Query(db, &struct{}{})
|
||||||
|
assert.NilError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSelectEXCEPT(t *testing.T) {
|
||||||
|
defer func() {
|
||||||
|
r := recover()
|
||||||
|
assert.Equal(t, r, "jet: MySQL does not support EXCEPT operator.")
|
||||||
|
}()
|
||||||
|
|
||||||
|
query := Payment.SELECT(Payment.PaymentID).LIMIT(1).OFFSET(10).
|
||||||
|
EXCEPT(Payment.SELECT(Payment.PaymentID).LIMIT(1).OFFSET(2)).LIMIT(1)
|
||||||
|
|
||||||
|
//fmt.Println(query.DebugSql())
|
||||||
|
|
||||||
|
err := query.Query(db, &struct{}{})
|
||||||
|
assert.NilError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSelectUNION_ALL(t *testing.T) {
|
||||||
|
expectedSQL := `
|
||||||
|
(
|
||||||
|
(
|
||||||
|
SELECT payment.payment_id AS "payment.payment_id"
|
||||||
|
FROM dvds.payment
|
||||||
|
LIMIT ?
|
||||||
|
OFFSET ?
|
||||||
|
)
|
||||||
|
UNION ALL
|
||||||
|
(
|
||||||
|
SELECT payment.payment_id AS "payment.payment_id"
|
||||||
|
FROM dvds.payment
|
||||||
|
LIMIT ?
|
||||||
|
OFFSET ?
|
||||||
|
)
|
||||||
|
);
|
||||||
|
`
|
||||||
|
query := UNION_ALL(
|
||||||
|
Payment.SELECT(Payment.PaymentID).LIMIT(1).OFFSET(10),
|
||||||
|
Payment.SELECT(Payment.PaymentID).LIMIT(1).OFFSET(2),
|
||||||
|
)
|
||||||
|
|
||||||
|
//fmt.Println(query.Sql())
|
||||||
|
|
||||||
|
testutils.AssertStatementSql(t, query, expectedSQL, int64(1), int64(10), int64(1), int64(2))
|
||||||
|
|
||||||
|
query2 := Payment.SELECT(Payment.PaymentID).LIMIT(1).OFFSET(10).
|
||||||
|
UNION_ALL(Payment.SELECT(Payment.PaymentID).LIMIT(1).OFFSET(2))
|
||||||
|
|
||||||
|
testutils.AssertStatementSql(t, query2, expectedSQL, int64(1), int64(10), int64(1), int64(2))
|
||||||
|
|
||||||
|
err := query.Query(db, &struct{}{})
|
||||||
|
assert.NilError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestJoinQueryStruct(t *testing.T) {
|
func TestJoinQueryStruct(t *testing.T) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue