|
| 1 | +{{define "copyfromCodeGoSqlDriver"}} |
| 2 | +{{range .GoQueries}} |
| 3 | +{{if eq .Cmd ":copyfrom" }} |
| 4 | +var readerHandlerSequenceFor{{.MethodName}} uint32 = 1 |
| 5 | + |
| 6 | +func convertRowsFor{{.MethodName}}(w *io.PipeWriter, {{.Arg.SlicePair}}) { |
| 7 | + e := mysqltsv.NewEncoder(w, {{ len .Arg.Fields }}, nil) |
| 8 | + for _, row := range {{.Arg.Name}} { |
| 9 | +{{- with $arg := .Arg }} |
| 10 | +{{- range $arg.Fields}} |
| 11 | +{{- if eq .Type "string"}} |
| 12 | + e.AppendString({{if eq (len $arg.Fields) 1}}row{{else}}row.{{.Name}}{{end}}) |
| 13 | +{{- else if eq .Type "[]byte"}} |
| 14 | + e.AppendBytes({{if eq (len $arg.Fields) 1}}row{{else}}row.{{.Name}}{{end}}) |
| 15 | +{{- else}} |
| 16 | + e.AppendValue({{if eq (len $arg.Fields) 1}}row{{else}}row.{{.Name}}{{end}}) |
| 17 | +{{- end}} |
| 18 | +{{- end}} |
| 19 | +{{- end}} |
| 20 | + } |
| 21 | + w.CloseWithError(e.Close()) |
| 22 | +} |
| 23 | + |
| 24 | +{{range .Comments}}//{{.}} |
| 25 | +{{end -}} |
| 26 | +// {{.MethodName}} uses MySQL's LOAD DATA LOCAL INFILE and is not atomic. |
| 27 | +// |
| 28 | +// Errors and duplicate keys are treated as warnings and insertion will |
| 29 | +// continue, even without an error for some cases. Use this in a transaction |
| 30 | +// and use SHOW WARNINGS to check for any problems and roll back if you want to. |
| 31 | +// |
| 32 | +// Check the documentation for more information: |
| 33 | +// https://dev.mysql.com/doc/refman/8.0/en/load-data.html#load-data-error-handling |
| 34 | +func (q *Queries) {{.MethodName}}(ctx context.Context{{if $.EmitMethodsWithDBArgument}}, db DBTX{{end}}, {{.Arg.SlicePair}}) (int64, error) { |
| 35 | + pr, pw := io.Pipe() |
| 36 | + defer pr.Close() |
| 37 | + rh := fmt.Sprintf("{{.MethodName}}_%d", atomic.AddUint32(&readerHandlerSequenceFor{{.MethodName}}, 1)) |
| 38 | + mysql.RegisterReaderHandler(rh, func() io.Reader { return pr }) |
| 39 | + defer mysql.DeregisterReaderHandler(rh) |
| 40 | + go convertRowsFor{{.MethodName}}(pw, {{.Arg.Name}}) |
| 41 | + // The string interpolation is necessary because LOAD DATA INFILE requires |
| 42 | + // the file name to be given as a literal string. |
| 43 | + result, err := {{if (not $.EmitMethodsWithDBArgument)}}q.{{end}}db.ExecContext(ctx, fmt.Sprintf("LOAD DATA LOCAL INFILE '%s' INTO TABLE {{.TableIdentifierForMySQL}} %s ({{range $index, $name := .Arg.ColumnNames}}{{if gt $index 0}}, {{end}}{{$name}}{{end}})", "Reader::" + rh, mysqltsv.Escaping)) |
| 44 | + if err != nil { |
| 45 | + return 0, err |
| 46 | + } |
| 47 | + return result.RowsAffected() |
| 48 | +} |
| 49 | + |
| 50 | +{{end}} |
| 51 | +{{end}} |
| 52 | +{{end}} |
0 commit comments