<commit_before>/*-------------------------------------------------------------------------
 *
 * pgtclId.c
 *
 *	Contains Tcl "channel" interface routines, plus useful routines
 *	to convert between strings and pointers.  These are needed because
 *	everything in Tcl is a string, but in C, pointers to data structures
 *	are needed.
 *
 *	ASSUMPTION:  sizeof(long) >= sizeof(void*)
 *
 * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 * IDENTIFICATION
 *	  $Id$
 *
 *-------------------------------------------------------------------------
 */

#include <errno.h>
#include <string.h>
#include <libpq-fe.h>

#include "pgtclCmds.h"
#include "pgtclId.h"

static int
PgEndCopy(Pg_ConnectionId * connid, int *errorCodePtr, int writing)
{
	connid->res_copyStatus = RES_COPY_NONE;
	if (writing && PQPutCopyEnd(connid->conn, NULL) != 1)
	{
		PQclear(connid->results[connid->res_copy]);
		connid->results[connid->res_copy] =
			PQmakeEmptyPGresult(connid->conn, PGRES_BAD_RESPONSE);
		connid->res_copy = -1;
		*errorCodePtr = EIO;
		return -1;
	}
	else
	{
		PQclear(connid->results[connid->res_copy]);
		connid->results[connid->res_copy] =
			PQmakeEmptyPGresult(connid->conn, PGRES_COMMAND_OK);
		connid->res_copy = -1;
		return 0;
	}
}

/*
 *	Called when reading data (via gets) for a copy <rel> to stdout.
 */
int
PgInputProc(DRIVER_INPUT_PROTO)
{
	Pg_ConnectionId *connid;
	PGconn	   *conn;
	int			avail;

	connid = (Pg_ConnectionId *) cData;
	conn = connid->conn;

	if (connid->res_copy < 0 ||
	 PQresultStatus(connid->results[connid->res_copy]) != PGRES_COPY_OUT)
	{
		*errorCodePtr = EBUSY;
		return -1;
	}

	/*
	 * Read any newly arrived data into libpq's buffer, thereby clearing
	 * the socket's read-ready condition.
	 */
	if (!PQconsumeInput(conn))
	{
		*errorCodePtr = EIO;
		return -1;
	}

	/* Move data from libpq's buffer to Tcl's. */

	switch(avail = PQgetCopyData(conn, buf, bufSize)) {
	  case -2: {
		*errorCodePtr = EIO;
		return -1;
	  }
	  case -1: {
		return PgEndCopy(connid, errorCodePtr, 0);
	  }
	}

	return avail;
}

/*
 *	Called when writing data (via puts) for a copy <rel> from stdin
 */
int
PgOutputProc(DRIVER_OUTPUT_PROTO)
{
	Pg_ConnectionId *connid;
	PGconn	   *conn;
	int         endcopy = 0;

	connid = (Pg_ConnectionId *) cData;
	conn = connid->conn;

	if (connid->res_copy < 0 ||
	  PQresultStatus(connid->results[connid->res_copy]) != PGRES_COPY_IN)
	{<commit_msg>Pass (char **) and free returned buffer from PQgetCopyData.<commit_after>/*-------------------------------------------------------------------------
 *
 * pgtclId.c
 *
 *	Contains Tcl "channel" interface routines, plus useful routines
 *	to convert between strings and pointers.  These are needed because
 *	everything in Tcl is a string, but in C, pointers to data structures
 *	are needed.
 *
 *	ASSUMPTION:  sizeof(long) >= sizeof(void*)
 *
 * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 * IDENTIFICATION
 *	  $Id$
 *
 *-------------------------------------------------------------------------
 */

#include <errno.h>
#include <string.h>
#include <libpq-fe.h>

#include "pgtclCmds.h"
#include "pgtclId.h"

static int
PgEndCopy(Pg_ConnectionId * connid, int *errorCodePtr, int writing)
{
	connid->res_copyStatus = RES_COPY_NONE;
	if (writing && PQputCopyEnd(connid->conn, NULL) != 1)
	{
		PQclear(connid->results[connid->res_copy]);
		connid->results[connid->res_copy] =
			PQmakeEmptyPGresult(connid->conn, PGRES_BAD_RESPONSE);
		connid->res_copy = -1;
		*errorCodePtr = EIO;
		return -1;
	}
	else
	{
		PQclear(connid->results[connid->res_copy]);
		connid->results[connid->res_copy] =
			PQmakeEmptyPGresult(connid->conn, PGRES_COMMAND_OK);
		connid->res_copy = -1;
		return 0;
	}
}

/*
 *	Called when reading data (via gets) for a copy <rel> to stdout.
 */
int
PgInputProc(DRIVER_INPUT_PROTO)
{
	Pg_ConnectionId *connid;
	PGconn	   *conn;
	int			avail;
	char	*bufPtr = NULL;

	connid = (Pg_ConnectionId *) cData;
	conn = connid->conn;

	if (connid->res_copy < 0 ||
	 PQresultStatus(connid->results[connid->res_copy]) != PGRES_COPY_OUT)
	{
		*errorCodePtr = EBUSY;
		return -1;
	}

	/*
	 * Read any newly arrived data into libpq's buffer, thereby clearing
	 * the socket's read-ready condition.
	 */
	if (!PQconsumeInput(conn))
	{
		*errorCodePtr = EIO;
		return -1;
	}

	/* Move data from libpq's buffer to Tcl's. */

	switch(avail = PQgetCopyData(conn, &bufPtr, bufSize)) {
	  case -2: {
		*errorCodePtr = EIO;
		return -1;
	  }
	  case -1: {
		return PgEndCopy(connid, errorCodePtr, 0);
	  }
	}

	if(bufPtr) {
		memcpy (buf, bufPtr, avail);
		PQfreemem(bufPtr);
	}

	return avail;
}

/*
 *	Called when writing data (via puts) for a copy <rel> from stdin
 */
int
PgOutputProc(DRIVER_OUTPUT_PROTO)
{
	Pg_ConnectionId *connid;
	PGconn	   *conn;
	int         endcopy = 0;

	connid = (Pg_ConnectionId *) cData;
	conn = connid->conn;

	if (connid->res_copy < 0 ||
	  PQresultStatus(connid->results[connid->res_copy]) != PGRES_COPY_IN)
	{
{'fraction_non_alphanumeric': 0.18243769470404986, 'fraction_numerical': 0.010124610591900311, 'mean_word_length': 2.957627118644068, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 59, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '184524', 'n_tokens_mistral': 2022, 'n_tokens_neox': 1878, 'n_words': 440}