package pq

import (
	
	
	
	
	
)

var (
	errCopyInClosed               = errors.New("pq: copyin statement has already been closed")
	errBinaryCopyNotSupported     = errors.New("pq: only text format supported for COPY")
	errCopyToNotSupported         = errors.New("pq: COPY TO is not supported")
	errCopyNotSupportedOutsideTxn = errors.New("pq: COPY is only allowed inside a transaction")
	errCopyInProgress             = errors.New("pq: COPY in progress")
)
CopyIn creates a COPY FROM statement which can be prepared with Tx.Prepare(). The target table should be visible in search_path.
func ( string,  ...string) string {
	 := "COPY " + QuoteIdentifier() + " ("
	for ,  := range  {
		if  != 0 {
			 += ", "
		}
		 += QuoteIdentifier()
	}
	 += ") FROM STDIN"
	return 
}
CopyInSchema creates a COPY FROM statement which can be prepared with Tx.Prepare().
func (,  string,  ...string) string {
	 := "COPY " + QuoteIdentifier() + "." + QuoteIdentifier() + " ("
	for ,  := range  {
		if  != 0 {
			 += ", "
		}
		 += QuoteIdentifier()
	}
	 += ") FROM STDIN"
	return 
}

type copyin struct {
	cn      *conn
	buffer  []byte
	rowData chan []byte
	done    chan bool

	closed bool

	sync.Mutex // guards err
	err        error
}

const ciBufferSize = 64 * 1024
flush buffer before the buffer is filled up and needs reallocation
const ciBufferFlushSize = 63 * 1024

func ( *conn) ( string) ( driver.Stmt,  error) {
	if !.isInTransaction() {
		return nil, errCopyNotSupportedOutsideTxn
	}

	 := &copyin{
		cn:      ,
		buffer:  make([]byte, 0, ciBufferSize),
		rowData: make(chan []byte),
		done:    make(chan bool, 1),
add CopyData identifier + 4 bytes for message length
	.buffer = append(.buffer, 'd', 0, 0, 0, 0)

	 := .writeBuf('Q')
	.string()
	.send()

:
	for {
		,  := .recv1()
		switch  {
		case 'G':
			if .byte() != 0 {
				 = errBinaryCopyNotSupported
				break 
			}
			go .resploop()
			return , nil
		case 'H':
			 = errCopyToNotSupported
			break 
		case 'E':
			 = parseError()
		case 'Z':
			if  == nil {
				.setBad()
				errorf("unexpected ReadyForQuery in response to COPY")
			}
			.processReadyForQuery()
			return nil, 
		default:
			.setBad()
			errorf("unknown response for copy query: %q", )
		}
	}
something went wrong, abort COPY before we return
	 = .writeBuf('f')
	.string(.Error())
	.send()

	for {
		,  := .recv1()
		switch  {
		case 'c', 'C', 'E':
correctly aborted, we're done
			.processReadyForQuery()
			return nil, 
		default:
			.setBad()
			errorf("unknown response for CopyFail: %q", )
		}
	}
}

set message length (without message identifier)
	binary.BigEndian.PutUint32([1:], uint32(len()-1))

	,  := .cn.c.Write()
	if  != nil {
		panic()
	}
}

func ( *copyin) () {
	for {
		var  readBuf
		,  := .cn.recvMessage(&)
		if  != nil {
			.setBad()
			.setError()
			.done <- true
			return
		}
		switch  {
complete
NoticeResponse
		case 'Z':
			.cn.processReadyForQuery(&)
			.done <- true
			return
		case 'E':
			 := parseError(&)
			.setError()
		default:
			.setBad()
			.setError(fmt.Errorf("unknown response during CopyIn: %q", ))
			.done <- true
			return
		}
	}
}

func ( *copyin) () {
	.Lock()
	.cn.bad = true
	.Unlock()
}

func ( *copyin) () bool {
	.Lock()
	 := .cn.bad
	.Unlock()
	return 
}

func ( *copyin) () bool {
	.Lock()
	 := (.err != nil)
	.Unlock()
	return 
}
setError() sets ci.err if one has not been set already. Caller must not be holding ci.Mutex.
func ( *copyin) ( error) {
	.Lock()
	if .err == nil {
		.err = 
	}
	.Unlock()
}

func ( *copyin) () int {
	return -1
}

func ( *copyin) ( []driver.Value) ( driver.Rows,  error) {
	return nil, ErrNotSupported
}
Exec inserts values into the COPY stream. The insert is asynchronous and Exec can return errors from previous Exec calls to the same COPY stmt. You need to call Exec(nil) to sync the COPY stream and to get any errors from pending data, since Stmt.Close() doesn't return errors to the user.
func ( *copyin) ( []driver.Value) ( driver.Result,  error) {
	if .closed {
		return nil, errCopyInClosed
	}

	if .isBad() {
		return nil, driver.ErrBadConn
	}
	defer .cn.errRecover(&)

	if .isErrorSet() {
		return nil, .err
	}

	if len() == 0 {
		return driver.RowsAffected(0), .Close()
	}

	 := len()
	for ,  := range  {
		.buffer = appendEncodedText(&.cn.parameterStatus, .buffer, )
		if  < -1 {
			.buffer = append(.buffer, '\t')
		}
	}

	.buffer = append(.buffer, '\n')

	if len(.buffer) > ciBufferFlushSize {
reset buffer, keep bytes for message identifier and length
		.buffer = .buffer[:5]
	}

	return driver.RowsAffected(0), nil
}

func ( *copyin) () ( error) {
	if .closed { // Don't do anything, we're already closed
		return nil
	}
	.closed = true

	if .isBad() {
		return driver.ErrBadConn
	}
	defer .cn.errRecover(&)

	if len(.buffer) > 0 {
		.flush(.buffer)
Avoid touching the scratch buffer as resploop could be using it.
	 = .cn.sendSimpleMessage('c')
	if  != nil {
		return 
	}

	<-.done
	.cn.inCopy = false

	if .isErrorSet() {
		 = .err
		return 
	}
	return nil