Add support for Update statements.

This commit is contained in:
zer0sub 2019-04-14 17:55:10 +02:00
parent b287521f1a
commit 70d6f84375
12 changed files with 422 additions and 286 deletions

View file

@ -34,16 +34,6 @@ type UnionStatement interface {
Offset(offset int64) UnionStatement
}
type UpdateStatement interface {
Statement
Set(column Column, expression Expression) UpdateStatement
Where(expression BoolExpression) UpdateStatement
OrderBy(clauses ...OrderByClause) UpdateStatement
Limit(limit int64) UpdateStatement
Comment(comment string) UpdateStatement
}
type DeleteStatement interface {
Statement
@ -250,151 +240,6 @@ func (us *unionStatementImpl) String() (sql string, err error) {
return buf.String(), nil
}
//
// UPDATE statement ===========================================================
//
func newUpdateStatement(table WritableTable) UpdateStatement {
return &updateStatementImpl{
table: table,
updateValues: make(map[Column]Expression),
limit: -1,
}
}
type updateStatementImpl struct {
table WritableTable
updateValues map[Column]Expression
where BoolExpression
order *listClause
limit int64
comment string
}
func (u *updateStatementImpl) Execute(db *sql.DB, data interface{}) error {
return nil
}
func (u *updateStatementImpl) Set(
column Column,
expression Expression) UpdateStatement {
u.updateValues[column] = expression
return u
}
func (u *updateStatementImpl) Where(expression BoolExpression) UpdateStatement {
u.where = expression
return u
}
func (u *updateStatementImpl) OrderBy(
clauses ...OrderByClause) UpdateStatement {
u.order = newOrderByListClause(clauses...)
return u
}
func (u *updateStatementImpl) Limit(limit int64) UpdateStatement {
u.limit = limit
return u
}
func (u *updateStatementImpl) Comment(comment string) UpdateStatement {
u.comment = comment
return u
}
func (u *updateStatementImpl) String() (sql string, err error) {
buf := new(bytes.Buffer)
_, _ = buf.WriteString("UPDATE ")
if err = writeComment(u.comment, buf); err != nil {
return
}
if u.table == nil {
return "", errors.Newf("nil tableName. Generated sql: %s", buf.String())
}
if err = u.table.SerializeSql(buf); err != nil {
return
}
if len(u.updateValues) == 0 {
return "", errors.Newf(
"No column updated. Generated sql: %s",
buf.String())
}
_, _ = buf.WriteString(" SET ")
addComma := false
// Sorting is too hard in go, just create a second map ...
updateValues := make(map[string]Expression)
for col, expr := range u.updateValues {
if col == nil {
return "", errors.Newf(
"nil column. Generated sql: %s",
buf.String())
}
updateValues[col.Name()] = expr
}
for _, col := range u.table.Columns() {
val, inMap := updateValues[col.Name()]
if !inMap {
continue
}
if addComma {
_, _ = buf.WriteString(", ")
}
if val == nil {
return "", errors.Newf(
"nil value. Generated sql: %s",
buf.String())
}
if err = col.SerializeSql(buf); err != nil {
return
}
_ = buf.WriteByte('=')
if err = val.SerializeSql(buf); err != nil {
return
}
addComma = true
}
if u.where == nil {
return "", errors.Newf(
"Updating without a WHERE clause. Generated sql: %s",
buf.String())
}
_, _ = buf.WriteString(" WHERE ")
if err = u.where.SerializeSql(buf); err != nil {
return
}
if u.order != nil {
_, _ = buf.WriteString(" ORDER BY ")
if err = u.order.SerializeSql(buf); err != nil {
return
}
}
if u.limit >= 0 {
_, _ = buf.WriteString(fmt.Sprintf(" LIMIT %d", u.limit))
}
return buf.String(), nil
}
//
// DELETE statement ===========================================================
//
@ -565,7 +410,7 @@ func (s *unlockStatementImpl) String() (sql string, err error) {
return "UNLOCK TABLES", nil
}
// Set GTID_NEXT statement returns a SQL statement that can be used to explicitly set the next GTID.
// SET GTID_NEXT statement returns a SQL statement that can be used to explicitly set the next GTID.
func NewGtidNextStatement(sid []byte, gno uint64) GtidNextStatement {
return &gtidNextStatementImpl{
sid: sid,