github.com/angenalZZZ/gofunc@v0.0.0-20210507121333-48ff1be3917b/data/bulk/gorm-bulk/bulk_insert_extend.go (about)

     1  package gormbulk
     2  
     3  import (
     4  	"fmt"
     5  	"time"
     6  
     7  	"github.com/angenalZZZ/gofunc/f"
     8  	"github.com/dop251/goja"
     9  	"github.com/jinzhu/gorm"
    10  )
    11  
    12  // BulkInsertByJs executes the query to insert multiple records at once.
    13  func BulkInsertByJs(db *gorm.DB, objects []map[string]interface{}, chunkSize int, javascript string, interval time.Duration, varRecords ...string) error {
    14  	var (
    15  		fnName = "records"
    16  		vm     = goja.New()
    17  		res    goja.Value
    18  		err    error
    19  	)
    20  
    21  	if len(varRecords) > 0 {
    22  		fnName = varRecords[0]
    23  	}
    24  
    25  	defer func() { vm.ClearInterrupt() }()
    26  
    27  	// Split records with specified size not to exceed Database parameter limit
    28  	for _, records := range f.SplitObjectMaps(objects, chunkSize) {
    29  		// Input records
    30  		vm.Set(fnName, records)
    31  
    32  		// Output sql
    33  		if res, err = vm.RunString(javascript); err != nil {
    34  			return fmt.Errorf("the table script error, must contain array %q, error: %s", fnName, err.Error())
    35  		} else if res == nil {
    36  			continue
    37  		}
    38  
    39  		val := res.Export()
    40  		if val == nil {
    41  			continue
    42  		}
    43  
    44  		switch sql := val.(type) {
    45  		case string:
    46  			if len(sql) < 20 {
    47  				continue
    48  			}
    49  			if err := db.Exec(sql).Error; err != nil {
    50  				return err
    51  			}
    52  		case []string:
    53  			for _, s := range sql {
    54  				if len(s) < 20 {
    55  					continue
    56  				}
    57  				if err := db.Exec(s).Error; err != nil {
    58  					return err
    59  				}
    60  			}
    61  		}
    62  
    63  		if interval > 0 {
    64  			time.Sleep(interval)
    65  		}
    66  	}
    67  	return nil
    68  }
    69  
    70  // BulkInsertByJsFunction executes the query to insert multiple records at once.
    71  func BulkInsertByJsFunction(db *gorm.DB, objects []map[string]interface{}, chunkSize int, javascript, functionName string, interval time.Duration) error {
    72  	var (
    73  		vm = goja.New()
    74  		fn func([]map[string]interface{}) interface{}
    75  	)
    76  
    77  	defer func() { vm.ClearInterrupt() }()
    78  
    79  	if _, err := vm.RunString(javascript); err != nil {
    80  		return err
    81  	}
    82  
    83  	val := vm.Get(functionName)
    84  	if val == nil {
    85  		return fmt.Errorf("js function %q not found", functionName)
    86  	}
    87  
    88  	if err := vm.ExportTo(val, &fn); err != nil {
    89  		return fmt.Errorf("js function %q not exported %s", functionName, err.Error())
    90  	}
    91  
    92  	// Split records with specified size not to exceed Database parameter limit
    93  	for _, records := range f.SplitObjectMaps(objects, chunkSize) {
    94  		// Output sql
    95  		val := fn(records)
    96  		if val == nil {
    97  			continue
    98  		}
    99  
   100  		switch sql := val.(type) {
   101  		case string:
   102  			if len(sql) < 20 {
   103  				continue
   104  			}
   105  			if err := db.Exec(sql).Error; err != nil {
   106  				return err
   107  			}
   108  		case []string:
   109  			for _, s := range sql {
   110  				if len(s) < 20 {
   111  					continue
   112  				}
   113  				if err := db.Exec(s).Error; err != nil {
   114  					return err
   115  				}
   116  			}
   117  		}
   118  
   119  		if interval > 0 {
   120  			time.Sleep(interval)
   121  		}
   122  	}
   123  	return nil
   124  }