fix: failed to migrate
This commit is contained in:
+39
-4
@@ -85,6 +85,7 @@ type copyFrom struct {
|
||||
columnNames []string
|
||||
rowSrc CopyFromSource
|
||||
readerErrChan chan error
|
||||
mode QueryExecMode
|
||||
}
|
||||
|
||||
func (ct *copyFrom) run(ctx context.Context) (int64, error) {
|
||||
@@ -105,9 +106,29 @@ func (ct *copyFrom) run(ctx context.Context) (int64, error) {
|
||||
}
|
||||
quotedColumnNames := cbuf.String()
|
||||
|
||||
sd, err := ct.conn.Prepare(ctx, "", fmt.Sprintf("select %s from %s", quotedColumnNames, quotedTableName))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
var sd *pgconn.StatementDescription
|
||||
switch ct.mode {
|
||||
case QueryExecModeExec, QueryExecModeSimpleProtocol:
|
||||
// These modes don't support the binary format. Before the inclusion of the
|
||||
// QueryExecModes, Conn.Prepare was called on every COPY operation to get
|
||||
// the OIDs. These prepared statements were not cached.
|
||||
//
|
||||
// Since that's the same behavior provided by QueryExecModeDescribeExec,
|
||||
// we'll default to that mode.
|
||||
ct.mode = QueryExecModeDescribeExec
|
||||
fallthrough
|
||||
case QueryExecModeCacheStatement, QueryExecModeCacheDescribe, QueryExecModeDescribeExec:
|
||||
var err error
|
||||
sd, err = ct.conn.getStatementDescription(
|
||||
ctx,
|
||||
ct.mode,
|
||||
fmt.Sprintf("select %s from %s", quotedColumnNames, quotedTableName),
|
||||
)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("statement description failed: %w", err)
|
||||
}
|
||||
default:
|
||||
return 0, fmt.Errorf("unknown QueryExecMode: %v", ct.mode)
|
||||
}
|
||||
|
||||
r, w := io.Pipe()
|
||||
@@ -167,8 +188,13 @@ func (ct *copyFrom) run(ctx context.Context) (int64, error) {
|
||||
}
|
||||
|
||||
func (ct *copyFrom) buildCopyBuf(buf []byte, sd *pgconn.StatementDescription) (bool, []byte, error) {
|
||||
const sendBufSize = 65536 - 5 // The packet has a 5-byte header
|
||||
lastBufLen := 0
|
||||
largestRowLen := 0
|
||||
|
||||
for ct.rowSrc.Next() {
|
||||
lastBufLen = len(buf)
|
||||
|
||||
values, err := ct.rowSrc.Values()
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
@@ -185,7 +211,15 @@ func (ct *copyFrom) buildCopyBuf(buf []byte, sd *pgconn.StatementDescription) (b
|
||||
}
|
||||
}
|
||||
|
||||
if len(buf) > 65536 {
|
||||
rowLen := len(buf) - lastBufLen
|
||||
if rowLen > largestRowLen {
|
||||
largestRowLen = rowLen
|
||||
}
|
||||
|
||||
// Try not to overflow size of the buffer PgConn.CopyFrom will be reading into. If that happens then the nature of
|
||||
// io.Pipe means that the next Read will be short. This can lead to pathological send sizes such as 65531, 13, 65531
|
||||
// 13, 65531, 13, 65531, 13.
|
||||
if len(buf) > sendBufSize-largestRowLen {
|
||||
return true, buf, nil
|
||||
}
|
||||
}
|
||||
@@ -208,6 +242,7 @@ func (c *Conn) CopyFrom(ctx context.Context, tableName Identifier, columnNames [
|
||||
columnNames: columnNames,
|
||||
rowSrc: rowSrc,
|
||||
readerErrChan: make(chan error),
|
||||
mode: c.config.DefaultQueryExecMode,
|
||||
}
|
||||
|
||||
return ct.run(ctx)
|
||||
|
||||
Reference in New Issue
Block a user