genmai.go
func (db *DB) Insert(obj interface{}) (affected int64, err error) {
	objs, rtype, tableName, err := db.tableObjs("Insert", obj)
	if err != nil {
		return -1, err
	}
	if len(objs) < 1 {
		return 0, nil
	}
	for _, obj := range objs {
		if hook, ok := obj.(BeforeInserter); ok {
			if err := hook.BeforeInsert(); err != nil {
				return -1, err
			}
		}
	}
	fieldIndexes := db.collectFieldIndexes(rtype, nil)
	cols := make([]string, len(fieldIndexes))
	for i, index := range fieldIndexes {
		cols[i] = db.dialect.Quote(db.columnFromTag(rtype.FieldByIndex(index)))
	}
	var args []interface{}
	for _, obj := range objs {
		rv := reflect.Indirect(reflect.ValueOf(obj))
		for _, index := range fieldIndexes {
			args = append(args, rv.FieldByIndex(index).Interface())
		}
	}
	numHolders := 0
	values := make([]string, len(objs))
	holders := make([]string, len(cols))
	for i := 0; i < len(values); i++ {
		for j := 0; j < len(holders); j++ {
			holders[j] = db.dialect.PlaceHolder(numHolders)
			numHolders++
		}
		values[i] = fmt.Sprintf("(%s)", strings.Join(holders, ", "))
	}
	query := fmt.Sprintf("INSERT INTO %s (%s) VALUES %s",
		db.dialect.Quote(tableName),
		strings.Join(cols, ", "),
		strings.Join(values, ", "),
	)
	stmt, err := db.prepare(query, args...)
	if err != nil {
		return -1, err
	}
	defer stmt.Close()
	result, err := stmt.Exec(args...)
	if err != nil {
		return -1, err
	}
	affected, _ = result.RowsAffected()
	if len(objs) == 1 {
		if pkIdx := db.findPKIndex(rtype, nil); len(pkIdx) > 0 {
			field := rtype.FieldByIndex(pkIdx)
			if db.isAutoIncrementable(&field) {
				id, err := db.LastInsertId()
				if err != nil {
					return affected, err
				}
				rv := reflect.Indirect(reflect.ValueOf(objs[0])).FieldByIndex(pkIdx)
				for rv.Kind() == reflect.Ptr {
					rv = rv.Elem()
				}
				rv.Set(reflect.ValueOf(id).Convert(rv.Type()))
			}
		}
	}
	for _, obj := range objs {
		if hook, ok := obj.(AfterInserter); ok {
			if err := hook.AfterInsert(); err != nil {
				return affected, err
			}
		}
	}
	return affected, nil
}
func (db *DB) Insert(obj interface{}) (affected int64, err error) {
	objs, rtype, tableName, err := db.tableObjs("Insert", obj)
	if err != nil {
		return -1, err
	}
	if len(objs) < 1 {
		return 0, nil
	}
	for _, obj := range objs {
		if hook, ok := obj.(BeforeInserter); ok {
			if err := hook.BeforeInsert(); err != nil {
				return -1, err
			}
		}
	}
	fieldIndexes := db.collectFieldIndexes(rtype, nil)
	cols := make([]string, len(fieldIndexes))
	for i, index := range fieldIndexes {
		cols[i] = db.dialect.Quote(db.columnFromTag(rtype.FieldByIndex(index)))
	}
	var args []interface{}
	for _, obj := range objs {
		rv := reflect.Indirect(reflect.ValueOf(obj))
		for _, index := range fieldIndexes {
			args = append(args, rv.FieldByIndex(index).Interface())
		}
	}
	numHolders := 0
	values := make([]string, len(objs))
	holders := make([]string, len(cols))
	for i := 0; i < len(values); i++ {
		for j := 0; j < len(holders); j++ {
			holders[j] = db.dialect.PlaceHolder(numHolders)
			numHolders++
		}
		values[i] = fmt.Sprintf("(%s)", strings.Join(holders, ", "))
	}
	query := fmt.Sprintf("INSERT INTO %s (%s) VALUES %s",
		db.dialect.Quote(tableName),
		strings.Join(cols, ", "),
		strings.Join(values, ", "),
	)
	stmt, err := db.prepare(query, args...)
	if err != nil {
		return -1, err
	}
	defer stmt.Close()
	result, err := stmt.Exec(args...)
	if err != nil {
		return -1, err
	}
	affected, _ = result.RowsAffected()
	if len(objs) == 1 {
		if pkIdx := db.findPKIndex(rtype, nil); len(pkIdx) > 0 {
			field := rtype.FieldByIndex(pkIdx)
			if db.isAutoIncrementable(&field) {
				id, err := db.LastInsertId()
				if err != nil {
					return affected, err
				}
				rv := reflect.Indirect(reflect.ValueOf(objs[0])).FieldByIndex(pkIdx)
				for rv.Kind() == reflect.Ptr {
					rv = rv.Elem()
				}
				rv.Set(reflect.ValueOf(id).Convert(rv.Type()))
			}
		}
	}
	for _, obj := range objs {
		if hook, ok := obj.(AfterInserter); ok {
			if err := hook.AfterInsert(); err != nil {
				return affected, err
			}
		}
	}
	return affected, nil
}
// Insert inserts one or more records to the database table.
// The obj must be pointer to struct or slice of struct. If a struct have a
// field which specified "pk" struct tag on type of autoincrementable, it
// won't be used to as an insert value.
// Insert sets the last inserted id to the primary key of the instance of the given obj if obj is single.
// Insert returns the number of rows affected by insert.