Add support for INSERT statements.

This commit is contained in:
zer0sub 2019-04-07 09:58:12 +02:00
parent d84deb8745
commit 599a8c537a
15 changed files with 586 additions and 277 deletions

View file

@ -12,17 +12,6 @@ import (
type Statement interface {
// String returns generated SQL as string.
String() (sql string, err error)
Execute(db *sql.DB, destination interface{}) error
}
type InsertStatement interface {
Statement
// Add a row of values to the insert statement.
Add(row ...Expression) InsertStatement
AddOnDuplicateKeyUpdate(col Column, expr Expression) InsertStatement
Comment(comment string) InsertStatement
IgnoreDuplicates(ignore bool) InsertStatement
}
// By default, rows selected by a UNION statement are out-of-order
@ -261,183 +250,6 @@ func (us *unionStatementImpl) String() (sql string, err error) {
return buf.String(), nil
}
//
// INSERT Statement ============================================================
//
func newInsertStatement(
t WritableTable,
columns ...Column) InsertStatement {
return &insertStatementImpl{
table: t,
columns: columns,
rows: make([][]Expression, 0, 1),
onDuplicateKeyUpdates: make([]columnAssignment, 0, 0),
}
}
type columnAssignment struct {
col Column
expr Expression
}
type insertStatementImpl struct {
table WritableTable
columns []Column
rows [][]Expression
onDuplicateKeyUpdates []columnAssignment
comment string
ignore bool
}
func (i *insertStatementImpl) Execute(db *sql.DB, data interface{}) error {
return nil
}
func (s *insertStatementImpl) Add(
row ...Expression) InsertStatement {
s.rows = append(s.rows, row)
return s
}
func (s *insertStatementImpl) AddOnDuplicateKeyUpdate(
col Column,
expr Expression) InsertStatement {
s.onDuplicateKeyUpdates = append(
s.onDuplicateKeyUpdates,
columnAssignment{col, expr})
return s
}
func (s *insertStatementImpl) IgnoreDuplicates(ignore bool) InsertStatement {
s.ignore = ignore
return s
}
func (s *insertStatementImpl) Comment(comment string) InsertStatement {
s.comment = comment
return s
}
func (s *insertStatementImpl) String() (sql string, err error) {
buf := new(bytes.Buffer)
_, _ = buf.WriteString("INSERT ")
if s.ignore {
_, _ = buf.WriteString("IGNORE ")
}
_, _ = buf.WriteString("INTO ")
if err = writeComment(s.comment, buf); err != nil {
return
}
if s.table == nil {
return "", errors.Newf("nil tableName. Generated sql: %s", buf.String())
}
if err = s.table.SerializeSql(buf); err != nil {
return
}
if len(s.columns) == 0 {
return "", errors.Newf(
"No column specified. Generated sql: %s",
buf.String())
}
_, _ = buf.WriteString(" (")
for i, col := range s.columns {
if i > 0 {
_ = buf.WriteByte(',')
}
if col == nil {
return "", errors.Newf(
"nil column in columns list. Generated sql: %s",
buf.String())
}
if err = col.SerializeSql(buf, FOR_PROJECTION); err != nil {
return
}
}
if len(s.rows) == 0 {
return "", errors.Newf(
"No row specified. Generated sql: %s",
buf.String())
}
_, _ = buf.WriteString(") VALUES (")
for row_i, row := range s.rows {
if row_i > 0 {
_, _ = buf.WriteString(", (")
}
if len(row) != len(s.columns) {
return "", errors.Newf(
"# of values does not match # of columns. Generated sql: %s",
buf.String())
}
for col_i, value := range row {
if col_i > 0 {
_ = buf.WriteByte(',')
}
if value == nil {
return "", errors.Newf(
"nil value in row %d col %d. Generated sql: %s",
row_i,
col_i,
buf.String())
}
if err = value.SerializeSql(buf); err != nil {
return
}
}
_ = buf.WriteByte(')')
}
if len(s.onDuplicateKeyUpdates) > 0 {
_, _ = buf.WriteString(" ON DUPLICATE KEY UPDATE ")
for i, colExpr := range s.onDuplicateKeyUpdates {
if i > 0 {
_, _ = buf.WriteString(", ")
}
if colExpr.col == nil {
return "", errors.Newf(
"nil column in on duplicate key update list. "+"Generated sql: %s",
buf.String())
}
if err = colExpr.col.SerializeSql(buf, FOR_PROJECTION); err != nil {
return
}
_ = buf.WriteByte('=')
if colExpr.expr == nil {
return "", errors.Newf(
"nil expression in on duplicate key update list. "+"Generated sql: %s",
buf.String())
}
if err = colExpr.expr.SerializeSql(buf); err != nil {
return
}
}
}
return buf.String(), nil
}
//
// UPDATE statement ===========================================================
//