diff --git a/insert.go b/insert.go index 1f617422..8d68e333 100644 --- a/insert.go +++ b/insert.go @@ -78,8 +78,16 @@ func (d *insertData) ToSql() (sqlStr string, args []interface{}, err error) { sql.WriteString(" ") } - if len(d.Options) > 0 { - sql.WriteString(strings.Join(d.Options, " ")) + options := make([]string, 0) + optionsMap := make(map[string]bool) + for _, opt := range d.Options { + if _, ok := optionsMap[opt]; !ok { + options = append(options, opt) + optionsMap[opt] = true + } + } + if len(options) > 0 { + sql.WriteString(strings.Join(options, " ")) sql.WriteString(" ") } diff --git a/insert_test.go b/insert_test.go index 6d0db9f6..ff183bf8 100644 --- a/insert_test.go +++ b/insert_test.go @@ -101,3 +101,28 @@ func TestInsertBuilderReplace(t *testing.T) { assert.Equal(t, expectedSQL, sql) } + +func TestInsertBuilderDuplicateOptions(t *testing.T) { + b := Insert(""). + Prefix("WITH prefix AS ?", 0). + Into("a"). + Options("DELAYED", "DELAYED", "IGNORE"). + Columns("b", "c"). + Values(1, 2). + Values(3, Expr("? + 1", 4)). + OnConflict("DO NOTHING"). + Returning("d", "e") + + sql, args, err := b.ToSql() + assert.NoError(t, err) + + expectedSQL := + "WITH prefix AS ? " + + "INSERT DELAYED IGNORE INTO a (b,c) VALUES (?,?),(?,? + 1) " + + "ON CONFLICT DO NOTHING " + + "RETURNING d, e" + assert.Equal(t, expectedSQL, sql) + + expectedArgs := []interface{}{0, 1, 2, 3, 4} + assert.Equal(t, expectedArgs, args) +} diff --git a/select.go b/select.go index ad5312e2..e5d645ce 100644 --- a/select.go +++ b/select.go @@ -84,8 +84,16 @@ func (d *selectData) toSql() (sqlStr string, args []interface{}, err error) { sql.WriteString("SELECT ") - if len(d.Options) > 0 { - sql.WriteString(strings.Join(d.Options, " ")) + options := make([]string, 0) + optionsMap := make(map[string]bool) + for _, opt := range d.Options { + if _, ok := optionsMap[opt]; !ok { + options = append(options, opt) + optionsMap[opt] = true + } + } + if len(options) > 0 { + sql.WriteString(strings.Join(options, " ")) sql.WriteString(" ") } diff --git a/select_test.go b/select_test.go index 5982a94a..4b625fd0 100644 --- a/select_test.go +++ b/select_test.go @@ -249,6 +249,20 @@ func TestSelectWithEmptyStringWhereClause(t *testing.T) { assert.Equal(t, "SELECT * FROM users", sql) } +func TestSelectBuilderDuplicateDistinct(t *testing.T) { + sql, _, err := Select("a", "b"). + Distinct(). + Distinct(). + Columns("c"). + From("e"). + ToSql() + + assert.NoError(t, err) + + expectedSql := "SELECT DISTINCT a, b, c FROM e" + assert.Equal(t, expectedSql, sql) +} + func ExampleSelect() { Select("id", "created", "first_name").From("users") // ... continue building up your query