Skip to content

Instantly share code, notes, and snippets.

@yutakahashi114
Last active March 26, 2021 12:40
Show Gist options
  • Save yutakahashi114/9d713e3868cf96a761104ce75ae7ed19 to your computer and use it in GitHub Desktop.
Save yutakahashi114/9d713e3868cf96a761104ce75ae7ed19 to your computer and use it in GitHub Desktop.
type config struct {
returningColumns []string
onConflict string
}
type Option func(*config)
func Returning(columns ...string) Option {
return func(c *config) {
c.returningColumns = columns
}
}
func OnConflict(onConflict string) Option {
return func(c *config) {
c.onConflict = onConflict
}
}
func (c config) optionalSQL() string {
returning := ""
if len(c.returningColumns) > 0 {
returning = fmt.Sprintf(" RETURNING %s", strings.Join(c.returningColumns, ","))
}
onConflict := ""
if c.onConflict != "" {
onConflict = fmt.Sprintf(" ON CONFLICT %s", c.onConflict)
}
return onConflict + returning
}
func (c config) hasReturn() bool {
return len(c.returningColumns) > 0
}
func BulkInsert(db xorm.Interface, inserter bulkInserter, options ...Option) ([]map[string]string, error) {
insertCount := inserter.Len()
if insertCount == 0 {
return nil, nil
}
c := &config{}
for _, opt := range options {
opt(c)
}
var results []map[string]string
if c.hasReturn() {
results = make([]map[string]string, 0, insertCount)
}
optionalSQL := c.optionalSQL()
valuesString := inserter.Values() + ","
argCount := len(inserter.Args(0))
insertLimit := pqArgLimit/argCount - 1
for start := 0; start < insertCount; start += insertLimit {
end := start + insertLimit
if end > insertCount {
end = insertCount
}
var values strings.Builder
values.Grow(len([]byte(valuesString)) * (end - start))
args := make([]interface{}, 0, (end-start)*argCount)
for i := start; i < end; i++ {
args = append(args, inserter.Args(i)...)
values.WriteString(valuesString)
}
sql := fmt.Sprintf(
"INSERT INTO %s (%s) VALUES %s%s",
inserter.TableName(),
inserter.Columns(),
strings.TrimRight(values.String(), ","),
optionalSQL,
)
result, err := db.QueryString(append([]interface{}{sql}, args...)...)
if err != nil {
return nil, err
}
if c.hasReturn() {
results = append(results, result...)
}
}
return results, nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment