(ctx context.Context)
| 116 | } |
| 117 | |
| 118 | func (ct *copyFrom) run(ctx context.Context) (int64, error) { |
| 119 | if ct.conn.copyFromTracer != nil { |
| 120 | ctx = ct.conn.copyFromTracer.TraceCopyFromStart(ctx, ct.conn, TraceCopyFromStartData{ |
| 121 | TableName: ct.tableName, |
| 122 | ColumnNames: ct.columnNames, |
| 123 | }) |
| 124 | } |
| 125 | |
| 126 | quotedTableName := ct.tableName.Sanitize() |
| 127 | cbuf := &bytes.Buffer{} |
| 128 | for i, cn := range ct.columnNames { |
| 129 | if i != 0 { |
| 130 | cbuf.WriteString(", ") |
| 131 | } |
| 132 | cbuf.WriteString(quoteIdentifier(cn)) |
| 133 | } |
| 134 | quotedColumnNames := cbuf.String() |
| 135 | |
| 136 | var sd *pgconn.StatementDescription |
| 137 | switch ct.mode { |
| 138 | case QueryExecModeExec, QueryExecModeSimpleProtocol: |
| 139 | // These modes don't support the binary format. Before the inclusion of the |
| 140 | // QueryExecModes, Conn.Prepare was called on every COPY operation to get |
| 141 | // the OIDs. These prepared statements were not cached. |
| 142 | // |
| 143 | // Since that's the same behavior provided by QueryExecModeDescribeExec, |
| 144 | // we'll default to that mode. |
| 145 | ct.mode = QueryExecModeDescribeExec |
| 146 | fallthrough |
| 147 | case QueryExecModeCacheStatement, QueryExecModeCacheDescribe, QueryExecModeDescribeExec: |
| 148 | var err error |
| 149 | sd, err = ct.conn.getStatementDescription( |
| 150 | ctx, |
| 151 | ct.mode, |
| 152 | fmt.Sprintf("select %s from %s", quotedColumnNames, quotedTableName), |
| 153 | ) |
| 154 | if err != nil { |
| 155 | return 0, fmt.Errorf("statement description failed: %w", err) |
| 156 | } |
| 157 | default: |
| 158 | return 0, fmt.Errorf("unknown QueryExecMode: %v", ct.mode) |
| 159 | } |
| 160 | |
| 161 | r, w := io.Pipe() |
| 162 | doneChan := make(chan struct{}) |
| 163 | |
| 164 | go func() { |
| 165 | defer close(doneChan) |
| 166 | |
| 167 | // Purposely NOT using defer w.Close(). See https://github.com/golang/go/issues/24283. |
| 168 | buf := ct.conn.wbuf |
| 169 | |
| 170 | buf = append(buf, "PGCOPY\n\377\r\n\000"...) |
| 171 | buf = pgio.AppendInt32(buf, 0) |
| 172 | buf = pgio.AppendInt32(buf, 0) |
| 173 | |
| 174 | moreRows := true |
| 175 | for moreRows { |
no test coverage detected