SHARE
TWEET

Untitled

a guest Sep 20th, 2019 76 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. package bui
  2.  
  3. import (
  4.     "encoding/json"
  5.     "errors"
  6.     "fmt"
  7.     "strings"
  8. )
  9.  
  10. var (
  11.     ErrEmptyQuery = errors.New("empty query")
  12.     chunkSize     = 100
  13. )
  14.  
  15. func BulkSaveBuilder(objects []map[string]interface{}, tableName string) ([]string, error) {
  16.     if len(objects) == 0 {
  17.         return []string{}, ErrEmptyQuery
  18.     }
  19.  
  20.     chunks := splitToChunks(objects, chunkSize)
  21.     keys := getKeys(objects[0])
  22.  
  23.     rawKeys := strings.Join(keys, ", ")
  24.  
  25.     var updateKeys []string
  26.     for _, key := range keys {
  27.         updateKeys = append(updateKeys, fmt.Sprintf("%s = VALUES(%s)", key, key))
  28.     }
  29.  
  30.     rawUpdate := strings.Join(updateKeys, ", ")
  31.  
  32.     var queries []string
  33.     for _, chunk := range chunks {
  34.         var valueGroups [][]interface{}
  35.         for _, obj := range chunk {
  36.             var valueGroup []interface{}
  37.             for _, key := range keys {
  38.                 valueGroup = append(valueGroup, obj[key])
  39.             }
  40.             valueGroups = append(valueGroups, valueGroup)
  41.         }
  42.  
  43.         JSONValues, err := json.Marshal(valueGroups)
  44.         if err != nil {
  45.             return []string{}, err
  46.         }
  47.  
  48.         rawValues := strings.ReplaceAll(fmt.Sprintf("%s", JSONValues), "[", "(")
  49.         rawValues = strings.ReplaceAll(rawValues, "]", ")")
  50.  
  51.         q := fmt.Sprintf(
  52.             "INSERT INTO `%s` (%s) VALUES %s ON DUPLICATE KEY UPDATE %s",
  53.             tableName, rawKeys, rawValues[1:len(rawValues)-1], rawUpdate,
  54.         )
  55.         queries = append(queries, q)
  56.     }
  57.  
  58.     return queries, nil
  59. }
  60.  
  61. func getKeys(myMap map[string]interface{}) []string {
  62.     keys := make([]string, 0, len(myMap))
  63.     for key := range myMap {
  64.         keys = append(keys, key)
  65.     }
  66.     return keys
  67. }
  68.  
  69. func splitToChunks(arr []map[string]interface{}, lim int) [][]map[string]interface{} {
  70.     var chunk []map[string]interface{}
  71.     chunks := make([][]map[string]interface{}, 0, len(arr)/lim+1)
  72.     for len(arr) >= lim {
  73.         chunk, arr = arr[:lim], arr[lim:]
  74.         chunks = append(chunks, chunk)
  75.     }
  76.     if len(arr) > 0 {
  77.         chunks = append(chunks, arr[:])
  78.     }
  79.     return chunks
  80. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top