// note this function is only used for benchmarks -- it doesn't escape tableName // or columnNames func multiInsert(conn *pgx.Conn, tableName string, columnNames []string, rowSrc pgx.CopyToSource) (int, error) { maxRowsPerInsert := 65535 / len(columnNames) rowsThisInsert := 0 rowCount := 0 sqlBuf := &bytes.Buffer{} args := make(pgx.QueryArgs, 0) resetQuery := func() { sqlBuf.Reset() fmt.Fprintf(sqlBuf, "insert into %s(%s) values", tableName, strings.Join(columnNames, ", ")) args = args[0:0] rowsThisInsert = 0 } resetQuery() tx, err := conn.Begin() if err != nil { return 0, err } defer tx.Rollback() for rowSrc.Next() { if rowsThisInsert > 0 { sqlBuf.WriteByte(',') } sqlBuf.WriteByte('(') values, err := rowSrc.Values() if err != nil { return 0, err } for i, val := range values { if i > 0 { sqlBuf.WriteByte(',') } sqlBuf.WriteString(args.Append(val)) } sqlBuf.WriteByte(')') rowsThisInsert++ if rowsThisInsert == maxRowsPerInsert { _, err := tx.Exec(sqlBuf.String(), args...) if err != nil { return 0, err } rowCount += rowsThisInsert resetQuery() } } if rowsThisInsert > 0 { _, err := tx.Exec(sqlBuf.String(), args...) if err != nil { return 0, err } rowCount += rowsThisInsert } if err := tx.Commit(); err != nil { return 0, nil } return rowCount, nil }