Add implicit cross join support

This commit is contained in:
go-jet 2021-05-03 18:48:15 +02:00
parent 0cba1f6401
commit 4ef0113f6b
6 changed files with 55 additions and 15 deletions

View file

@ -45,19 +45,25 @@ func (s *ClauseSelect) Serialize(statementType StatementType, out *SQLBuilder, o
// ClauseFrom struct // ClauseFrom struct
type ClauseFrom struct { type ClauseFrom struct {
Table Serializer Tables []Serializer
} }
// Serialize serializes clause into SQLBuilder // Serialize serializes clause into SQLBuilder
func (f *ClauseFrom) Serialize(statementType StatementType, out *SQLBuilder, options ...SerializeOption) { func (f *ClauseFrom) Serialize(statementType StatementType, out *SQLBuilder, options ...SerializeOption) {
if f.Table == nil { if len(f.Tables) == 0 { // SELECT statement does not have to have FROM clause
return return
} }
out.NewLine() out.NewLine()
out.WriteString("FROM") out.WriteString("FROM")
out.IncreaseIdent() out.IncreaseIdent()
f.Table.serialize(statementType, out, FallTrough(options)...) for i, table := range f.Tables {
if i > 0 {
out.WriteString(",")
out.NewLine()
}
table.serialize(statementType, out, FallTrough(options)...)
}
out.DecreaseIdent() out.DecreaseIdent()
} }

View file

@ -136,9 +136,6 @@ func (t *joinTableImpl) TableName() string {
return "" return ""
} }
func (t *joinTableImpl) AS(alias string) {
}
func (t *joinTableImpl) columns() []Column { func (t *joinTableImpl) columns() []Column {
var ret []Column var ret []Column

View file

@ -8,6 +8,7 @@ import (
"github.com/go-jet/jet/v2/internal/utils" "github.com/go-jet/jet/v2/internal/utils"
"github.com/go-jet/jet/v2/qrm" "github.com/go-jet/jet/v2/qrm"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"io/ioutil" "io/ioutil"
"os" "os"
@ -116,7 +117,12 @@ func AssertDebugStatementSql(t *testing.T, query jet.Statement, expectedQuery st
} }
debuqSql := query.DebugSql() debuqSql := query.DebugSql()
require.Equal(t, debuqSql, expectedQuery) if !assert.Equal(t, debuqSql, expectedQuery) {
fmt.Println("Expected: ")
fmt.Println(expectedQuery)
fmt.Println("Got: ")
fmt.Println(debuqSql)
}
} }
// AssertSerialize checks if clause serialize produces expected query and args // AssertSerialize checks if clause serialize produces expected query and args

View file

@ -41,7 +41,7 @@ type SelectStatement interface {
Expression Expression
DISTINCT() SelectStatement DISTINCT() SelectStatement
FROM(table ReadableTable) SelectStatement FROM(tables ...ReadableTable) SelectStatement
WHERE(expression BoolExpression) SelectStatement WHERE(expression BoolExpression) SelectStatement
GROUP_BY(groupByClauses ...jet.GroupByClause) SelectStatement GROUP_BY(groupByClauses ...jet.GroupByClause) SelectStatement
HAVING(boolExpression BoolExpression) SelectStatement HAVING(boolExpression BoolExpression) SelectStatement
@ -70,7 +70,9 @@ func newSelectStatement(table ReadableTable, projections []Projection) SelectSta
&newSelect.Limit, &newSelect.Offset, &newSelect.For, &newSelect.ShareLock) &newSelect.Limit, &newSelect.Offset, &newSelect.For, &newSelect.ShareLock)
newSelect.Select.ProjectionList = projections newSelect.Select.ProjectionList = projections
newSelect.From.Table = table if table != nil {
newSelect.From.Tables = []jet.Serializer{table}
}
newSelect.Limit.Count = -1 newSelect.Limit.Count = -1
newSelect.Offset.Count = -1 newSelect.Offset.Count = -1
newSelect.ShareLock.Name = "LOCK IN SHARE MODE" newSelect.ShareLock.Name = "LOCK IN SHARE MODE"
@ -103,8 +105,10 @@ func (s *selectStatementImpl) DISTINCT() SelectStatement {
return s return s
} }
func (s *selectStatementImpl) FROM(table ReadableTable) SelectStatement { func (s *selectStatementImpl) FROM(tables ...ReadableTable) SelectStatement {
s.From.Table = table for _, table := range tables {
s.From.Tables = append(s.From.Tables, table)
}
return s return s
} }

View file

@ -44,7 +44,7 @@ type SelectStatement interface {
Expression Expression
DISTINCT() SelectStatement DISTINCT() SelectStatement
FROM(table ReadableTable) SelectStatement FROM(tables ...ReadableTable) SelectStatement
WHERE(expression BoolExpression) SelectStatement WHERE(expression BoolExpression) SelectStatement
GROUP_BY(groupByClauses ...jet.GroupByClause) SelectStatement GROUP_BY(groupByClauses ...jet.GroupByClause) SelectStatement
HAVING(boolExpression BoolExpression) SelectStatement HAVING(boolExpression BoolExpression) SelectStatement
@ -76,7 +76,9 @@ func newSelectStatement(table ReadableTable, projections []Projection) SelectSta
&newSelect.Limit, &newSelect.Offset, &newSelect.For) &newSelect.Limit, &newSelect.Offset, &newSelect.For)
newSelect.Select.ProjectionList = projections newSelect.Select.ProjectionList = projections
newSelect.From.Table = table if table != nil {
newSelect.From.Tables = []jet.Serializer{table}
}
newSelect.Limit.Count = -1 newSelect.Limit.Count = -1
newSelect.Offset.Count = -1 newSelect.Offset.Count = -1
@ -106,8 +108,10 @@ func (s *selectStatementImpl) DISTINCT() SelectStatement {
return s return s
} }
func (s *selectStatementImpl) FROM(table ReadableTable) SelectStatement { func (s *selectStatementImpl) FROM(tables ...ReadableTable) SelectStatement {
s.From.Table = table for _, table := range tables {
s.From.Tables = append(s.From.Tables, table)
}
return s return s
} }

View file

@ -99,3 +99,26 @@ CROSS JOIN db.table2`)
CROSS JOIN db.table2 CROSS JOIN db.table2
CROSS JOIN db.table3`) CROSS JOIN db.table3`)
} }
func TestImplicitCROSS_JOIN(t *testing.T) {
assertDebugStatementSql(t,
SELECT(table1Col1, table2Col3).
FROM(table1, table2),
`
SELECT table1.col1 AS "table1.col1",
table2.col3 AS "table2.col3"
FROM db.table1,
db.table2;
`)
assertDebugStatementSql(t,
SELECT(
table1Col1, table2Col3,
).FROM(table1, table2, table3),
`
SELECT table1.col1 AS "table1.col1",
table2.col3 AS "table2.col3"
FROM db.table1,
db.table2,
db.table3;
`)
}