github.com/RevenueMonster/sqlike@v1.0.6/sqlike/insert.go (about)

     1  package sqlike
     2  
     3  import (
     4  	"context"
     5  	"database/sql"
     6  	"reflect"
     7  
     8  	"errors"
     9  
    10  	"github.com/RevenueMonster/sqlike/reflext"
    11  	"github.com/RevenueMonster/sqlike/sql/codec"
    12  	sqldialect "github.com/RevenueMonster/sqlike/sql/dialect"
    13  	sqldriver "github.com/RevenueMonster/sqlike/sql/driver"
    14  	sqlstmt "github.com/RevenueMonster/sqlike/sql/stmt"
    15  	"github.com/RevenueMonster/sqlike/sqlike/logs"
    16  	"github.com/RevenueMonster/sqlike/sqlike/options"
    17  )
    18  
    19  // InsertOne : insert single record. You should always pass in the address of input.
    20  func (tb *Table) InsertOne(ctx context.Context, src interface{}, opts ...*options.InsertOneOptions) (sql.Result, error) {
    21  	opt := new(options.InsertOneOptions)
    22  	if len(opts) > 0 && opts[0] != nil {
    23  		opt = opts[0]
    24  	}
    25  	v := reflect.ValueOf(src)
    26  	if !v.IsValid() {
    27  		return nil, ErrInvalidInput
    28  	}
    29  	t := v.Type()
    30  	if !reflext.IsKind(t, reflect.Ptr) {
    31  		return nil, ErrUnaddressableEntity
    32  	}
    33  
    34  	if v.IsNil() {
    35  		return nil, ErrNilEntity
    36  	}
    37  
    38  	arr := reflect.MakeSlice(reflect.SliceOf(t), 0, 1)
    39  	arr = reflect.Append(arr, v)
    40  	return insertMany(
    41  		ctx,
    42  		tb.dbName,
    43  		tb.name,
    44  		tb.pk,
    45  		tb.client.cache,
    46  		tb.codec,
    47  		tb.driver,
    48  		tb.dialect,
    49  		tb.logger,
    50  		arr.Interface(),
    51  		&opt.InsertOptions,
    52  	)
    53  }
    54  
    55  // Insert : insert multiple records. You should always pass in the address of the slice.
    56  func (tb *Table) Insert(ctx context.Context, src interface{}, opts ...*options.InsertOptions) (sql.Result, error) {
    57  	opt := new(options.InsertOptions)
    58  	if len(opts) > 0 && opts[0] != nil {
    59  		opt = opts[0]
    60  	}
    61  	return insertMany(
    62  		ctx,
    63  		tb.dbName,
    64  		tb.name,
    65  		tb.pk,
    66  		tb.client.cache,
    67  		tb.codec,
    68  		tb.driver,
    69  		tb.dialect,
    70  		tb.logger,
    71  		src,
    72  		opt,
    73  	)
    74  }
    75  
    76  func insertMany(ctx context.Context, dbName, tbName, pk string, cache reflext.StructMapper, cdc codec.Codecer, driver sqldriver.Driver, dialect sqldialect.Dialect, logger logs.Logger, src interface{}, opt *options.InsertOptions) (sql.Result, error) {
    77  	v := reflext.ValueOf(src)
    78  	if !v.IsValid() {
    79  		return nil, ErrInvalidInput
    80  	}
    81  
    82  	v = reflext.Indirect(v)
    83  	t := v.Type()
    84  	if !reflext.IsKind(t, reflect.Array) && !reflext.IsKind(t, reflect.Slice) {
    85  		return nil, errors.New("sqlike: insert only support array or slice of entity")
    86  	}
    87  
    88  	if v.Len() < 1 {
    89  		return nil, ErrInvalidInput
    90  	}
    91  
    92  	t = reflext.Deref(t.Elem())
    93  	if !reflext.IsKind(t, reflect.Struct) {
    94  		return nil, ErrUnaddressableEntity
    95  	}
    96  
    97  	def := cache.CodecByType(t)
    98  	stmt := sqlstmt.AcquireStmt(dialect)
    99  	defer sqlstmt.ReleaseStmt(stmt)
   100  
   101  	if err := dialect.InsertInto(
   102  		stmt,
   103  		dbName,
   104  		tbName,
   105  		pk,
   106  		cache,
   107  		cdc,
   108  		def.Properties(),
   109  		v,
   110  		opt,
   111  	); err != nil {
   112  		return nil, err
   113  	}
   114  	return sqldriver.Execute(
   115  		ctx,
   116  		driver,
   117  		stmt,
   118  		getLogger(logger, opt.Debug),
   119  	)
   120  }