MySQL: Add Where and Limit for Delete statement.
This commit is contained in:
parent
a3ae52c43c
commit
0dd976601e
6 changed files with 91 additions and 29 deletions
|
|
@ -5,7 +5,9 @@ import "github.com/go-jet/jet/internal/jet"
|
||||||
type DeleteStatement interface {
|
type DeleteStatement interface {
|
||||||
jet.Statement
|
jet.Statement
|
||||||
|
|
||||||
WHERE(expression BoolExpression) Statement
|
WHERE(expression BoolExpression) DeleteStatement
|
||||||
|
ORDER_BY(orderByClauses ...jet.OrderByClause) DeleteStatement
|
||||||
|
LIMIT(limit int64) DeleteStatement
|
||||||
}
|
}
|
||||||
|
|
||||||
type deleteStatementImpl struct {
|
type deleteStatementImpl struct {
|
||||||
|
|
@ -13,21 +15,34 @@ type deleteStatementImpl struct {
|
||||||
|
|
||||||
Delete jet.ClauseStatementBegin
|
Delete jet.ClauseStatementBegin
|
||||||
Where jet.ClauseWhere
|
Where jet.ClauseWhere
|
||||||
|
OrderBy jet.ClauseOrderBy
|
||||||
|
Limit jet.ClauseLimit
|
||||||
}
|
}
|
||||||
|
|
||||||
func newDeleteStatement(table Table) DeleteStatement {
|
func newDeleteStatement(table Table) DeleteStatement {
|
||||||
newDelete := &deleteStatementImpl{}
|
newDelete := &deleteStatementImpl{}
|
||||||
newDelete.StatementImpl = jet.NewStatementImpl(Dialect, jet.DeleteStatementType, newDelete, &newDelete.Delete,
|
newDelete.StatementImpl = jet.NewStatementImpl(Dialect, jet.DeleteStatementType, newDelete, &newDelete.Delete,
|
||||||
&newDelete.Where)
|
&newDelete.Where, &newDelete.OrderBy, &newDelete.Limit)
|
||||||
|
|
||||||
newDelete.Delete.Name = "DELETE FROM"
|
newDelete.Delete.Name = "DELETE FROM"
|
||||||
newDelete.Delete.Tables = append(newDelete.Delete.Tables, table)
|
newDelete.Delete.Tables = append(newDelete.Delete.Tables, table)
|
||||||
newDelete.Where.Mandatory = true
|
newDelete.Where.Mandatory = true
|
||||||
|
newDelete.Limit.Count = -1
|
||||||
|
|
||||||
return newDelete
|
return newDelete
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *deleteStatementImpl) WHERE(expression BoolExpression) Statement {
|
func (d *deleteStatementImpl) WHERE(expression BoolExpression) DeleteStatement {
|
||||||
d.Where.Condition = expression
|
d.Where.Condition = expression
|
||||||
return d
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *deleteStatementImpl) ORDER_BY(orderByClauses ...jet.OrderByClause) DeleteStatement {
|
||||||
|
s.OrderBy.List = orderByClauses
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *deleteStatementImpl) LIMIT(limit int64) DeleteStatement {
|
||||||
|
s.Limit.Count = limit
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,3 +15,12 @@ DELETE FROM db.table1
|
||||||
WHERE table1.col1 = ?;
|
WHERE table1.col1 = ?;
|
||||||
`, int64(1))
|
`, int64(1))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDeleteWithWhereOrderByLimit(t *testing.T) {
|
||||||
|
assertStatement(t, table1.DELETE().WHERE(table1Col1.EQ(Int(1))).ORDER_BY(table1Col1).LIMIT(1), `
|
||||||
|
DELETE FROM db.table1
|
||||||
|
WHERE table1.col1 = ?
|
||||||
|
ORDER BY table1.col1
|
||||||
|
LIMIT ?;
|
||||||
|
`, int64(1), int64(1))
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,19 +17,24 @@ type readableTable interface {
|
||||||
SELECT(projection jet.Projection, projections ...jet.Projection) SelectStatement
|
SELECT(projection jet.Projection, projections ...jet.Projection) SelectStatement
|
||||||
|
|
||||||
// Creates a inner join tableName Expression using onCondition.
|
// Creates a inner join tableName Expression using onCondition.
|
||||||
INNER_JOIN(table ReadableTable, onCondition BoolExpression) Table
|
INNER_JOIN(table ReadableTable, onCondition BoolExpression) joinSelectUpdateTable
|
||||||
|
|
||||||
// Creates a left join tableName Expression using onCondition.
|
// Creates a left join tableName Expression using onCondition.
|
||||||
LEFT_JOIN(table ReadableTable, onCondition BoolExpression) Table
|
LEFT_JOIN(table ReadableTable, onCondition BoolExpression) joinSelectUpdateTable
|
||||||
|
|
||||||
// Creates a right join tableName Expression using onCondition.
|
// Creates a right join tableName Expression using onCondition.
|
||||||
RIGHT_JOIN(table ReadableTable, onCondition BoolExpression) Table
|
RIGHT_JOIN(table ReadableTable, onCondition BoolExpression) joinSelectUpdateTable
|
||||||
|
|
||||||
// Creates a full join tableName Expression using onCondition.
|
// Creates a full join tableName Expression using onCondition.
|
||||||
FULL_JOIN(table ReadableTable, onCondition BoolExpression) Table
|
FULL_JOIN(table ReadableTable, onCondition BoolExpression) joinSelectUpdateTable
|
||||||
|
|
||||||
// Creates a cross join tableName Expression using onCondition.
|
// Creates a cross join tableName Expression using onCondition.
|
||||||
CROSS_JOIN(table ReadableTable) Table
|
CROSS_JOIN(table ReadableTable) joinSelectUpdateTable
|
||||||
|
}
|
||||||
|
|
||||||
|
type joinSelectUpdateTable interface {
|
||||||
|
ReadableTable
|
||||||
|
UPDATE(column jet.Column, columns ...jet.Column) UpdateStatement
|
||||||
}
|
}
|
||||||
|
|
||||||
type ReadableTable interface {
|
type ReadableTable interface {
|
||||||
|
|
@ -47,25 +52,25 @@ func (r *readableTableInterfaceImpl) SELECT(projection1 jet.Projection, projecti
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates a inner join tableName Expression using onCondition.
|
// Creates a inner join tableName Expression using onCondition.
|
||||||
func (r *readableTableInterfaceImpl) INNER_JOIN(table ReadableTable, onCondition BoolExpression) Table {
|
func (r *readableTableInterfaceImpl) INNER_JOIN(table ReadableTable, onCondition BoolExpression) joinSelectUpdateTable {
|
||||||
return newJoinTable(r.parent, table, jet.InnerJoin, onCondition)
|
return newJoinTable(r.parent, table, jet.InnerJoin, onCondition)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates a left join tableName Expression using onCondition.
|
// Creates a left join tableName Expression using onCondition.
|
||||||
func (r *readableTableInterfaceImpl) LEFT_JOIN(table ReadableTable, onCondition BoolExpression) Table {
|
func (r *readableTableInterfaceImpl) LEFT_JOIN(table ReadableTable, onCondition BoolExpression) joinSelectUpdateTable {
|
||||||
return newJoinTable(r.parent, table, jet.LeftJoin, onCondition)
|
return newJoinTable(r.parent, table, jet.LeftJoin, onCondition)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates a right join tableName Expression using onCondition.
|
// Creates a right join tableName Expression using onCondition.
|
||||||
func (r *readableTableInterfaceImpl) RIGHT_JOIN(table ReadableTable, onCondition BoolExpression) Table {
|
func (r *readableTableInterfaceImpl) RIGHT_JOIN(table ReadableTable, onCondition BoolExpression) joinSelectUpdateTable {
|
||||||
return newJoinTable(r.parent, table, jet.RightJoin, onCondition)
|
return newJoinTable(r.parent, table, jet.RightJoin, onCondition)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *readableTableInterfaceImpl) FULL_JOIN(table ReadableTable, onCondition BoolExpression) Table {
|
func (r *readableTableInterfaceImpl) FULL_JOIN(table ReadableTable, onCondition BoolExpression) joinSelectUpdateTable {
|
||||||
return newJoinTable(r.parent, table, jet.FullJoin, onCondition)
|
return newJoinTable(r.parent, table, jet.FullJoin, onCondition)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *readableTableInterfaceImpl) CROSS_JOIN(table ReadableTable) Table {
|
func (r *readableTableInterfaceImpl) CROSS_JOIN(table ReadableTable) joinSelectUpdateTable {
|
||||||
return newJoinTable(r.parent, table, jet.CrossJoin, nil)
|
return newJoinTable(r.parent, table, jet.CrossJoin, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,25 @@ WHERE link.name IN ('Gmail', 'Outlook');
|
||||||
testutils.AssertExec(t, deleteStmt, db, 2)
|
testutils.AssertExec(t, deleteStmt, db, 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDeleteWithWhereOrderByLimit(t *testing.T) {
|
||||||
|
initForDeleteTest(t)
|
||||||
|
|
||||||
|
var expectedSQL = `
|
||||||
|
DELETE FROM test_sample.link
|
||||||
|
WHERE link.name IN ('Gmail', 'Outlook')
|
||||||
|
ORDER BY link.name
|
||||||
|
LIMIT 1;
|
||||||
|
`
|
||||||
|
deleteStmt := Link.
|
||||||
|
DELETE().
|
||||||
|
WHERE(Link.Name.IN(String("Gmail"), String("Outlook"))).
|
||||||
|
ORDER_BY(Link.Name).
|
||||||
|
LIMIT(1)
|
||||||
|
|
||||||
|
testutils.AssertDebugStatementSql(t, deleteStmt, expectedSQL, "Gmail", "Outlook", int64(1))
|
||||||
|
testutils.AssertExec(t, deleteStmt, db, 1)
|
||||||
|
}
|
||||||
|
|
||||||
func TestDeleteQueryContext(t *testing.T) {
|
func TestDeleteQueryContext(t *testing.T) {
|
||||||
initForDeleteTest(t)
|
initForDeleteTest(t)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,14 +11,14 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
const genTestDir2 = "./.gentestdata2/mysql"
|
const genTestDirRoot = "./.gentestdata3"
|
||||||
|
const genTestDir3 = "./.gentestdata3/mysql"
|
||||||
|
|
||||||
func TestGenerator(t *testing.T) {
|
func TestGenerator(t *testing.T) {
|
||||||
|
err := os.RemoveAll(genTestDir3)
|
||||||
err := os.RemoveAll(genTestDir2)
|
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
err = mysql.Generate(genTestDir2, mysql.DBConnection{
|
err = mysql.Generate(genTestDir3, mysql.DBConnection{
|
||||||
Host: dbconfig.MySqLHost,
|
Host: dbconfig.MySqLHost,
|
||||||
Port: dbconfig.MySQLPort,
|
Port: dbconfig.MySQLPort,
|
||||||
User: dbconfig.MySQLUser,
|
User: dbconfig.MySQLUser,
|
||||||
|
|
@ -30,7 +30,7 @@ func TestGenerator(t *testing.T) {
|
||||||
|
|
||||||
assertGeneratedFiles(t)
|
assertGeneratedFiles(t)
|
||||||
|
|
||||||
err = os.RemoveAll(genTestDir2)
|
err = os.RemoveAll(genTestDirRoot)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -40,11 +40,11 @@ func TestCmdGenerator(t *testing.T) {
|
||||||
err := goInstallJet.Run()
|
err := goInstallJet.Run()
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
err = os.RemoveAll(genTestDir2)
|
err = os.RemoveAll(genTestDir3)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
cmd := exec.Command("jet", "-source=MySQL", "-dbname=dvds", "-host=localhost", "-port=3306",
|
cmd := exec.Command("jet", "-source=MySQL", "-dbname=dvds", "-host=localhost", "-port=3306",
|
||||||
"-user=jet", "-password=jet", "-path="+genTestDir2)
|
"-user=jet", "-password=jet", "-path="+genTestDir3)
|
||||||
|
|
||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
||||||
cmd.Stdout = os.Stdout
|
cmd.Stdout = os.Stdout
|
||||||
|
|
@ -54,37 +54,37 @@ func TestCmdGenerator(t *testing.T) {
|
||||||
|
|
||||||
assertGeneratedFiles(t)
|
assertGeneratedFiles(t)
|
||||||
|
|
||||||
err = os.RemoveAll(genTestDir2)
|
err = os.RemoveAll(genTestDirRoot)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func assertGeneratedFiles(t *testing.T) {
|
func assertGeneratedFiles(t *testing.T) {
|
||||||
// Table SQL Builder files
|
// Table SQL Builder files
|
||||||
tableSQLBuilderFiles, err := ioutil.ReadDir("./.gentestdata2/mysql/dvds/table")
|
tableSQLBuilderFiles, err := ioutil.ReadDir(genTestDir3 + "/dvds/table")
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
assertFileNameEqual(t, tableSQLBuilderFiles, "actor.go", "address.go", "category.go", "city.go", "country.go",
|
assertFileNameEqual(t, tableSQLBuilderFiles, "actor.go", "address.go", "category.go", "city.go", "country.go",
|
||||||
"customer.go", "film.go", "film_actor.go", "film_category.go", "inventory.go", "language.go",
|
"customer.go", "film.go", "film_actor.go", "film_category.go", "inventory.go", "language.go",
|
||||||
"payment.go", "rental.go", "staff.go", "store.go")
|
"payment.go", "rental.go", "staff.go", "store.go")
|
||||||
|
|
||||||
assertFileContent(t, "./.gentestdata2/mysql/dvds/table/actor.go", "\npackage table", actorSQLBuilderFile)
|
assertFileContent(t, genTestDir3+"/dvds/table/actor.go", "\npackage table", actorSQLBuilderFile)
|
||||||
|
|
||||||
// Enums SQL Builder files
|
// Enums SQL Builder files
|
||||||
enumFiles, err := ioutil.ReadDir("./.gentestdata2/mysql/dvds/enum")
|
enumFiles, err := ioutil.ReadDir(genTestDir3 + "/dvds/enum")
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
assertFileNameEqual(t, enumFiles, "film_list_rating.go", "film_rating.go", "nicer_but_slower_film_list_rating.go")
|
assertFileNameEqual(t, enumFiles, "film_list_rating.go", "film_rating.go", "nicer_but_slower_film_list_rating.go")
|
||||||
assertFileContent(t, "./.gentestdata2/mysql/dvds/enum/film_rating.go", "\npackage enum", mpaaRatingEnumFile)
|
assertFileContent(t, genTestDir3+"/dvds/enum/film_rating.go", "\npackage enum", mpaaRatingEnumFile)
|
||||||
|
|
||||||
// Model files
|
// Model files
|
||||||
modelFiles, err := ioutil.ReadDir("./.gentestdata2/mysql/dvds/model")
|
modelFiles, err := ioutil.ReadDir(genTestDir3 + "/dvds/model")
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
assertFileNameEqual(t, modelFiles, "actor.go", "address.go", "category.go", "city.go", "country.go",
|
assertFileNameEqual(t, modelFiles, "actor.go", "address.go", "category.go", "city.go", "country.go",
|
||||||
"customer.go", "film.go", "film_actor.go", "film_category.go", "inventory.go", "language.go",
|
"customer.go", "film.go", "film_actor.go", "film_category.go", "inventory.go", "language.go",
|
||||||
"payment.go", "rental.go", "staff.go", "store.go", "film_list_rating.go", "film_rating.go", "nicer_but_slower_film_list_rating.go")
|
"payment.go", "rental.go", "staff.go", "store.go", "film_list_rating.go", "film_rating.go", "nicer_but_slower_film_list_rating.go")
|
||||||
|
|
||||||
assertFileContent(t, "./.gentestdata2/mysql/dvds/model/actor.go", "\npackage model", actorModelFile)
|
assertFileContent(t, genTestDir3+"/dvds/model/actor.go", "\npackage model", actorModelFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
func assertFileContent(t *testing.T, filePath string, contentBegin string, expectedContent string) {
|
func assertFileContent(t *testing.T, filePath string, contentBegin string, expectedContent string) {
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/go-jet/jet/internal/testutils"
|
"github.com/go-jet/jet/internal/testutils"
|
||||||
. "github.com/go-jet/jet/mysql"
|
. "github.com/go-jet/jet/mysql"
|
||||||
|
"github.com/go-jet/jet/tests/.gentestdata/mysql/dvds/table"
|
||||||
"github.com/go-jet/jet/tests/.gentestdata/mysql/test_sample/model"
|
"github.com/go-jet/jet/tests/.gentestdata/mysql/test_sample/model"
|
||||||
. "github.com/go-jet/jet/tests/.gentestdata/mysql/test_sample/table"
|
. "github.com/go-jet/jet/tests/.gentestdata/mysql/test_sample/table"
|
||||||
"gotest.tools/assert"
|
"gotest.tools/assert"
|
||||||
|
|
@ -204,6 +205,19 @@ func TestUpdateExecContext(t *testing.T) {
|
||||||
assert.Error(t, err, "context deadline exceeded")
|
assert.Error(t, err, "context deadline exceeded")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestUpdateWithJoin(t *testing.T) {
|
||||||
|
query := table.Staff.
|
||||||
|
INNER_JOIN(table.Address, table.Address.AddressID.EQ(table.Staff.AddressID)).
|
||||||
|
UPDATE(table.Staff.LastName).
|
||||||
|
SET(String("New name")).
|
||||||
|
WHERE(table.Staff.StaffID.EQ(Int(1)))
|
||||||
|
|
||||||
|
//fmt.Println(query.DebugSql())
|
||||||
|
|
||||||
|
_, err := query.Exec(db)
|
||||||
|
assert.NilError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
func setupLinkTableForUpdateTest(t *testing.T) {
|
func setupLinkTableForUpdateTest(t *testing.T) {
|
||||||
|
|
||||||
cleanUpLinkTable(t)
|
cleanUpLinkTable(t)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue