Пример #1
0
/*
 * Execute SQL statement. For non-select statements only.
 */
int	zbx_db_vexecute(const char *fmt, va_list args)
{
	char	*sql = NULL;
	int	ret = ZBX_DB_OK;
	double	sec = 0;

#if defined(HAVE_IBM_DB2)
	SQLHANDLE	hstmt = 0;
	SQLRETURN	ret1;
	SQLLEN		row1;
	SQLLEN		rows = 0;
#elif defined(HAVE_MYSQL)
	int		status;
#elif defined(HAVE_ORACLE)
	OCIStmt		*stmthp = NULL;
	sword		err = OCI_SUCCESS;
#elif defined(HAVE_POSTGRESQL)
	PGresult	*result;
	char		*error = NULL;
#elif defined(HAVE_SQLITE3)
	int		err;
	char		*error = NULL;
#endif

	if (CONFIG_LOG_SLOW_QUERIES)
		sec = zbx_time();

	sql = fmt;
	//zabbix_log(LOG_LEVEL_DEBUG,"vexecute: %s",sql);

	if (0 == txn_init && 0 == txn_level)
		zabbix_log(LOG_LEVEL_DEBUG, "query without transaction detected");

	zabbix_log(LOG_LEVEL_DEBUG, "query [txnlev:%d] [%s]", txn_level, sql);

#if defined(HAVE_IBM_DB2)
	/* allocate a statement handle */
	if (SUCCEED != zbx_ibm_db2_success(SQLAllocHandle(SQL_HANDLE_STMT, ibm_db2.hdbc, &hstmt)))
		ret = ZBX_DB_DOWN;

	/* directly execute the statement; returns SQL_NO_DATA_FOUND when no rows were affected */
  	if (ZBX_DB_OK == ret && SUCCEED != zbx_ibm_db2_success_ext(SQLExecDirect(hstmt, (SQLCHAR *)sql, SQL_NTS)))
		ret = ZBX_DB_DOWN;

	/* get number of affected rows */
	if (ZBX_DB_OK == ret && SUCCEED != zbx_ibm_db2_success(SQLRowCount(hstmt, &rows)))
		ret = ZBX_DB_DOWN;

	/* process other SQL statements in the batch */
	while (ZBX_DB_OK == ret && SUCCEED == zbx_ibm_db2_success(ret1 = SQLMoreResults(hstmt)))
	{
		if (SUCCEED != zbx_ibm_db2_success(SQLRowCount(hstmt, &row1)))
			ret = ZBX_DB_DOWN;
		else
			rows += row1;
	}

	if (ZBX_DB_OK == ret && SQL_NO_DATA_FOUND != ret1)
		ret = ZBX_DB_DOWN;

	if (ZBX_DB_OK != ret)
	{
		zbx_ibm_db2_log_errors(SQL_HANDLE_DBC, ibm_db2.hdbc);
		zbx_ibm_db2_log_errors(SQL_HANDLE_STMT, hstmt);

		ret = (SQL_CD_TRUE == IBM_DB2server_status() ? ZBX_DB_FAIL : ZBX_DB_DOWN);
	}
	else if (0 <= rows)
	{
		ret = (int)rows;
	}

	if (hstmt)
		SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
#elif defined(HAVE_MYSQL)
	if (NULL == conn)
	{
		zabbix_errlog(ERR_Z3003);
		ret = ZBX_DB_FAIL;
	}
	else
	{
		if (0 != (status = mysql_query(conn, sql)))
		{
			zabbix_errlog(ERR_Z3005, mysql_errno(conn), mysql_error(conn), sql);

			switch (mysql_errno(conn))
			{
				case CR_CONN_HOST_ERROR:
				case CR_SERVER_GONE_ERROR:
				case CR_CONNECTION_ERROR:
				case CR_SERVER_LOST:
				case ER_SERVER_SHUTDOWN:
				case ER_ACCESS_DENIED_ERROR: /* wrong user or password */
				case ER_ILLEGAL_GRANT_FOR_TABLE: /* user without any privileges */
				case ER_TABLEACCESS_DENIED_ERROR:/* user without some privilege */
				case ER_UNKNOWN_ERROR:
					ret = ZBX_DB_DOWN;
					break;
				default:
					ret = ZBX_DB_FAIL;
					break;
			}
		}
		else
		{
			do
			{
				if (0 != mysql_field_count(conn))
				{
					zabbix_log(LOG_LEVEL_DEBUG, "cannot retrieve result set");
					break;
				}
				else
					ret += (int)mysql_affected_rows(conn);

				/* more results? -1 = no, >0 = error, 0 = yes (keep looping) */
				if (0 < (status = mysql_next_result(conn)))
					zabbix_errlog(ERR_Z3005, mysql_errno(conn), mysql_error(conn), sql);
			}
			while (0 == status);
		}
	}
#elif defined(HAVE_ORACLE)
	err = OCIHandleAlloc((dvoid *)oracle.envhp, (dvoid **)&stmthp, OCI_HTYPE_STMT, (size_t)0, (dvoid **)0);

	if (OCI_SUCCESS == err)
	{
		err = OCIStmtPrepare(stmthp, oracle.errhp, (text *)sql, (ub4)strlen((char *)sql),
				(ub4)OCI_NTV_SYNTAX, (ub4)OCI_DEFAULT);
	}

	if (OCI_SUCCESS == err)
	{
		err = OCIStmtExecute(oracle.svchp, stmthp, oracle.errhp, (ub4)1, (ub4)0,
				(CONST OCISnapshot *)NULL, (OCISnapshot *)NULL, OCI_COMMIT_ON_SUCCESS);

		if (OCI_SUCCESS == err)
		{
			ub4	nrows = 0;

			err = OCIAttrGet((void *)stmthp, OCI_HTYPE_STMT, (ub4 *)&nrows,
					  (ub4 *)0, OCI_ATTR_ROW_COUNT, oracle.errhp);

			ret = nrows;
		}
	}

	if (OCI_SUCCESS != err)
	{
		zabbix_errlog(ERR_Z3005, err, zbx_oci_error(err), sql);
		ret = (OCI_SERVER_NORMAL == OCI_DBserver_status() ? ZBX_DB_FAIL : ZBX_DB_DOWN);
	}

	if (NULL != stmthp)
	{
		(void)OCIHandleFree((dvoid *)stmthp, OCI_HTYPE_STMT);
		stmthp = NULL;
	}
#elif defined(HAVE_POSTGRESQL)
	result = PQexec(conn,sql);

	if (NULL == result)
	{
		zabbix_errlog(ERR_Z3005, 0, "result is NULL", sql);
		ret = (CONNECTION_OK == PQstatus(conn) ? ZBX_DB_FAIL : ZBX_DB_DOWN);
	}
	else if (PGRES_COMMAND_OK != PQresultStatus(result))
	{
		error = zbx_dsprintf(error, "%s:%s",
				PQresStatus(PQresultStatus(result)),
				PQresultErrorMessage(result));
		zabbix_errlog(ERR_Z3005, 0, error, sql);
		zbx_free(error);

		ret = (CONNECTION_OK == PQstatus(conn) ? ZBX_DB_FAIL : ZBX_DB_DOWN);
	}

	if (ZBX_DB_OK == ret)
		ret = atoi(PQcmdTuples(result));

	PQclear(result);
#elif defined(HAVE_SQLITE3)
	if (0 == txn_level && PHP_MUTEX_OK != php_sem_acquire(&sqlite_access))
	{
		zabbix_log(LOG_LEVEL_CRIT, "ERROR: unable to create lock on SQLite database");
		exit(FAIL);
	}

lbl_exec:
	if (SQLITE_OK != (err = sqlite3_exec(conn, sql, NULL, 0, &error)))
	{
		if (SQLITE_BUSY == err)
			goto lbl_exec;

		zabbix_errlog(ERR_Z3005, 0, error, sql);
		sqlite3_free(error);

		switch (err)
		{
			case SQLITE_ERROR:	/* SQL error or missing database; assuming SQL error, because if we
						   are this far into execution, zbx_db_connect() was successful */
			case SQLITE_NOMEM:	/* A malloc() failed */
			case SQLITE_TOOBIG:	/* String or BLOB exceeds size limit */
			case SQLITE_CONSTRAINT:	/* Abort due to constraint violation */
			case SQLITE_MISMATCH:	/* Data type mismatch */
				ret = ZBX_DB_FAIL;
				break;
			default:
				ret = ZBX_DB_DOWN;
				break;
		}
	}

	if (ZBX_DB_OK == ret)
		ret = sqlite3_changes(conn);

	if (0 == txn_level)
		php_sem_release(&sqlite_access);
#endif	/* HAVE_SQLITE3 */

	if (CONFIG_LOG_SLOW_QUERIES)
	{
		sec = zbx_time() - sec;
		if (sec > (double)CONFIG_LOG_SLOW_QUERIES / 1000.0)
			zabbix_log(LOG_LEVEL_WARNING, "slow query: " ZBX_FS_DBL " sec, \"%s\"", sec, sql);
	}


	return ret;
}
Пример #2
0
int
hb_main(const char* conninfo)
{
	PGconn	   *conn;
	PGresult   *res;
	PGnotify   *notify;
	int			nnotifies;
	int checked;
	int result;

	char number[5];
	char notify_buf[1024];

	srand((unsigned)time(NULL));

	/* Make a connection to the database */
	conn = PQconnectdb(conninfo);

	/* Check to see that the backend connection was successfully made */
	if (PQstatus(conn) != CONNECTION_OK)
	{
		elog(WARNING, "Connection to database failed: %s",
				PQerrorMessage(conn));
		exit_nicely(conn);
	}

	/*
	 * Issue LISTEN command to enable notifications from the rule's NOTIFY.
	 */
	res = PQexec(conn, "LISTEN HB_SV");
	if (PQresultStatus(res) != PGRES_COMMAND_OK)
	{
		elog(WARNING, "LISTEN command failed: %s", PQerrorMessage(conn));
		PQclear(res);
		exit_nicely(conn);
	}

	/*
	 * should PQclear PGresult whenever it is no longer needed to avoid memory
	 * leaks
	 */
	PQclear(res);

	/* Set Secret Number */
	memset(number, 0x00, 5);
	create_random_number(number);
	elog(LOG , "hb_worker: set secret number=%s\n", number);

	/* Quit after four notifies are received. */
	nnotifies = 0;
	while (1)
	{
		/*
		 * Sleep until something happens on the connection.  We use select(2)
		 * to wait for input, but you could also use poll() or similar
		 * facilities.
		 */
		int			sock;
		fd_set		input_mask;

		sock = PQsocket(conn);

		if (sock < 0)
			break;				/* shouldn't happen */

		FD_ZERO(&input_mask);
		FD_SET(sock, &input_mask);

		if (select(sock + 1, &input_mask, NULL, NULL, NULL) < 0)
		{
			elog(WARNING, "select() failed: %s\n", strerror(errno));
			exit_nicely(conn);
		}

		/* Now check for input */
		PQconsumeInput(conn);
		while ((notify = PQnotifies(conn)) != NULL)
		{
			checked = check_number(notify->extra);
			switch (checked) {
				case NUMBER_COMMAND:
					result = compare_numbers(number, notify->extra);
					if (GET_HITS(result) == 4) {
						// Notify Game Clear, and Set new number.
						elog(LOG, "hb_worker: NOTIFY HB_CL,'4 Hit! Conguratulatoins!, next new game.'\n");
						strcpy(notify_buf, "NOTIFY HB_CL,'4 Hit! Conguratulatoins!, next new game.'");
						PQexec(conn, notify_buf);
						create_random_number(number);
						elog(LOG, "hb_worker: set secret number=%s\n", number);

					} else {
						// Notify Hit&blow
						elog(LOG, "NOTIFY HB_CL,'%d Hit / %d Blow.'",
							GET_HITS(result), GET_BLOWS(result));
						sprintf(notify_buf, "NOTIFY HB_CL,'%d Hit / %d Blow.'",
							GET_HITS(result), GET_BLOWS(result));
						PQexec(conn, notify_buf);
					}
					break;
				case START_COMMAND:
					// Set New number.
					elog(LOG, "hb_worker: Set New number.");
					create_random_number(number);
					break;
				case QUIT_COMMAND:
					// nop
					break;
				case INVALID_COMMAND:
				default:
					// NOTIFY error status
					sprintf(notify_buf, "NOTIFY HB_CL,'Invalid data.(%s)'", notify->extra);
					PQexec(conn, notify_buf);
					break;
			}
			

			PQfreemem(notify);
			nnotifies++;
		}
	}

	elog(LOG, "Done.\n");

	/* close the connection to the database and cleanup */
	PQfinish(conn);

	return 0;
}
Пример #3
0
/* Complex checking of the query status */
    int
pgsql_query_checkstatus(PGresult *res)
{

    int status;
    int nFields;
    long long nTuples;

    /* 
       For successful queries, there are two options: either the query returns 
       results or not.  If it does not return data, but successfully completed, 
       then the status will be set to 
       PGRES_COMMAND_OK.  
       If success and returns tuples, then it will be set to 
       PGRES_TUPLES_OK 
       */


    status = PQresultStatus(res);

    if (PQresultStatus(res) == PGRES_COMMAND_OK)
    {
        /* Success but no results */
        IDL_Message(IDL_M_NAMED_GENERIC, IDL_MSG_INFO, PQcmdStatus(res));
        return(MYPG_NO_RESULT);
    }

    if (PQresultStatus(res) != PGRES_TUPLES_OK)
    {
        IDL_Message(IDL_M_NAMED_GENERIC, IDL_MSG_INFO, 
                PQresultErrorMessage(res));

        switch (status)
        {
            /* No results */
            case PGRES_COPY_IN:        return(MYPG_NO_RESULT);
            case PGRES_COPY_OUT:       return(MYPG_NO_RESULT);
            case PGRES_BAD_RESPONSE:   return(MYPG_NO_RESULT);
            case PGRES_NONFATAL_ERROR: return(MYPG_NO_RESULT);
                                       /* An error */
            case PGRES_FATAL_ERROR:    return(MYPG_FATAL_ERROR);
            default: break;
        } 
    }

    /* How many fields and rows did we return? */
    nFields = PQnfields(res);
    nTuples = PQntuples(res);

    /* Result is empty, either an error or this query returns no data */
    if (nTuples == 0) 
    {
        if (nFields == 0)
        {
            /* Query returns no data. Try to print a message to clarify */
            IDL_Message(IDL_M_NAMED_GENERIC, IDL_MSG_INFO, PQcmdStatus(res));
            return(MYPG_NO_RESULT);
        }
        else
            /* Probably nothing matched the query */
            return(MYPG_NO_RESULT);

    }

    return(MYPG_SUCCESS);

}
Пример #4
0
/*
 * Establish the connection to the primary server for XLOG streaming
 */
static bool
libpqrcv_connect(char *conninfo, XLogRecPtr startpoint)
{
	char		conninfo_repl[MAXCONNINFO + 18];
	char	   *primary_sysid;
	char		standby_sysid[32];
	TimeLineID	primary_tli;
	TimeLineID	standby_tli;
	PGresult   *res;
	char		cmd[64];

	/* Connect using deliberately undocumented parameter: replication */
	snprintf(conninfo_repl, sizeof(conninfo_repl), "%s replication=true", conninfo);

	streamConn = PQconnectdb(conninfo_repl);
	if (PQstatus(streamConn) != CONNECTION_OK)
		ereport(ERROR,
				(errmsg("could not connect to the primary server: %s",
						PQerrorMessage(streamConn))));

	/*
	 * Get the system identifier and timeline ID as a DataRow message from the
	 * primary server.
	 */
	res = libpqrcv_PQexec("IDENTIFY_SYSTEM");
	if (PQresultStatus(res) != PGRES_TUPLES_OK)
	{
		PQclear(res);
		ereport(ERROR,
				(errmsg("could not receive database system identifier and timeline ID from "
						"the primary server: %s",
						PQerrorMessage(streamConn))));
	}
	if (PQnfields(res) != 2 || PQntuples(res) != 1)
	{
		int			ntuples = PQntuples(res);
		int			nfields = PQnfields(res);

		PQclear(res);
		ereport(ERROR,
				(errmsg("invalid response from primary server"),
				 errdetail("Expected 1 tuple with 2 fields, got %d tuples with %d fields.",
						   ntuples, nfields)));
	}
	primary_sysid = PQgetvalue(res, 0, 0);
	primary_tli = pg_atoi(PQgetvalue(res, 0, 1), 4, 0);

	/*
	 * Confirm that the system identifier of the primary is the same as ours.
	 */
	snprintf(standby_sysid, sizeof(standby_sysid), UINT64_FORMAT,
			 GetSystemIdentifier());
	if (strcmp(primary_sysid, standby_sysid) != 0)
	{
		PQclear(res);
		ereport(ERROR,
				(errmsg("database system identifier differs between the primary and standby"),
				 errdetail("The primary's identifier is %s, the standby's identifier is %s.",
						   primary_sysid, standby_sysid)));
	}

	/*
	 * Confirm that the current timeline of the primary is the same as the
	 * recovery target timeline.
	 */
	standby_tli = GetRecoveryTargetTLI();
	PQclear(res);
	if (primary_tli != standby_tli)
		ereport(ERROR,
				(errmsg("timeline %u of the primary does not match recovery target timeline %u",
						primary_tli, standby_tli)));
	ThisTimeLineID = primary_tli;

	/* Start streaming from the point requested by startup process */
	snprintf(cmd, sizeof(cmd), "START_REPLICATION %X/%X",
			 startpoint.xlogid, startpoint.xrecoff);
	res = libpqrcv_PQexec(cmd);
	if (PQresultStatus(res) != PGRES_COPY_OUT)
	{
		PQclear(res);
		ereport(ERROR,
				(errmsg("could not start WAL streaming: %s",
						PQerrorMessage(streamConn))));
	}
	PQclear(res);

	justconnected = true;
	ereport(LOG,
			(errmsg("streaming replication successfully connected to primary")));

	return true;
}
Пример #5
0
/*
 * Run one permutation
 */
static void
run_permutation(TestSpec *testspec, int nsteps, Step **steps)
{
	PGresult *res;
	int i;

	printf("\nstarting permutation:");
	for (i = 0; i < nsteps; i++)
		printf(" %s", steps[i]->name);
	printf("\n");

	/* Perform setup */
	if (testspec->setupsql)
	{
		res = PQexec(conns[0], testspec->setupsql);
		if (PQresultStatus(res) != PGRES_COMMAND_OK)
		{
			fprintf(stderr, "setup failed: %s", PQerrorMessage(conns[0]));
			exit_nicely();
		}
		PQclear(res);
	}

	/* Perform per-session setup */
	for (i = 0; i < testspec->nsessions; i++)
	{
		if (testspec->sessions[i]->setupsql)
		{
			res = PQexec(conns[i], testspec->sessions[i]->setupsql);
			if (PQresultStatus(res) != PGRES_COMMAND_OK)
			{
				fprintf(stderr, "setup of session %s failed: %s",
						testspec->sessions[i]->name,
						PQerrorMessage(conns[0]));
				exit_nicely();
			}
			PQclear(res);
		}
	}

	/* Perform steps */
	for (i = 0; i < nsteps; i++)
	{
		Step *step = steps[i];
		printf("step %s: %s\n", step->name, step->sql);
		res = PQexec(conns[step->session], step->sql);

		switch(PQresultStatus(res))
		{
			case PGRES_COMMAND_OK:
				break;

			case PGRES_TUPLES_OK:
				printResultSet(res);
				break;

			case PGRES_FATAL_ERROR:
				/* Detail may contain xid values, so just show primary. */
				printf("%s:  %s\n", PQresultErrorField(res, PG_DIAG_SEVERITY),
					   PQresultErrorField(res, PG_DIAG_MESSAGE_PRIMARY));
				break;

			default:
				printf("unexpected result status: %s\n",
					   PQresStatus(PQresultStatus(res)));
		}
		PQclear(res);
	}

	/* Perform per-session teardown */
	for (i = 0; i < testspec->nsessions; i++)
	{
		if (testspec->sessions[i]->teardownsql)
		{
			res = PQexec(conns[i], testspec->sessions[i]->teardownsql);
			if (PQresultStatus(res) != PGRES_COMMAND_OK)
			{
				fprintf(stderr, "teardown of session %s failed: %s",
						testspec->sessions[i]->name,
						PQerrorMessage(conns[0]));
				/* don't exit on teardown failure */
			}
			PQclear(res);
		}
	}

	/* Perform teardown */
	if (testspec->teardownsql)
	{
		res = PQexec(conns[0], testspec->teardownsql);
		if (PQresultStatus(res) != PGRES_COMMAND_OK)
		{
			fprintf(stderr, "teardown failed: %s",
					PQerrorMessage(conns[0]));
			/* don't exit on teardown failure */

		}
		PQclear(res);
	}
}
Пример #6
0
/*
 * Transform a GML geometry to PostGIS EWKT
 * Return NULL on error
 */
buffer * ows_psql_gml_to_sql(ows * o, xmlNodePtr n, int srid)
{
    PGresult *res;
    xmlNodePtr g;
    buffer *result, *sql, *gml;

    assert(o);
    assert(n);

    g = ows_psql_recursive_parse_gml(o, n, NULL);
    if (!g) return NULL;    /* No Geometry founded in GML doc */

    /* Retrieve the sub doc and launch GML parse via PostGIS */
    gml = buffer_init();
    cgi_add_xml_into_buffer(gml, g);
    
    sql = buffer_init();
    buffer_add_str(sql, "SELECT ST_GeomFromGML('");
    buffer_add_str(sql, gml->buf);

    if (ows_version_get(o->postgis_version) >= 200) {
       buffer_add_str(sql, "',");
       buffer_add_int(sql, srid);
       buffer_add_str(sql, ")");
    } else { 
       /* Means PostGIS 1.5 */
       buffer_add_str(sql, "')");
    }

    res = ows_psql_exec(o, sql->buf);
    buffer_free(gml);

    /* GML Parse errors cases */
    if (PQresultStatus(res) != PGRES_TUPLES_OK || PQntuples(res) != 1) {
        buffer_free(sql);
        PQclear(res);
        return NULL;
    }

    result = buffer_init();
    buffer_add_str(result, PQgetvalue(res, 0, 0));
    PQclear(res);

    /* Check if geometry is valid */
    if (o->check_valid_geom) {

        buffer_empty(sql);
        buffer_add_str(sql, "SELECT ST_IsValid('");
        buffer_add_str(sql, result->buf);
        buffer_add_str(sql, "')");

        res = ows_psql_exec(o, sql->buf);

        if (    PQresultStatus(res) != PGRES_TUPLES_OK
             || PQntuples(res) != 1
             || (char) PQgetvalue(res, 0, 0)[0] !=  't') {
            buffer_free(sql);
            buffer_free(result);
            PQclear(res);
            return NULL;
        }
        PQclear(res);
    }

    buffer_free(sql);
 
    return result;
}
/*****************************************************
 * \brief Read a natural block of raster band data
 *****************************************************/
CPLErr PostGISRasterTileRasterBand::IReadBlock(CPL_UNUSED int nBlockXOff,
                                               CPL_UNUSED int nBlockYOff,
                                               void * pImage)
{
    CPLString osCommand;
    PGresult * poResult = NULL;
    int nWKBLength = 0;

    int nPixelSize = GDALGetDataTypeSize(eDataType)/8;

    PostGISRasterTileDataset * poRTDS =
        (PostGISRasterTileDataset *)poDS;

    // Get by PKID
    if (poRTDS->poRDS->pszPrimaryKeyName) {
        //osCommand.Printf("select ST_AsBinary(st_band(%s, %d),TRUE) from %s.%s where "
        osCommand.Printf("select st_band(%s, %d) from %s.%s where "
            "%s = '%s'", poRTDS->poRDS->pszColumn, nBand, poRTDS->poRDS->pszSchema, poRTDS->poRDS->pszTable,
            poRTDS->poRDS->pszPrimaryKeyName, poRTDS->pszPKID);

    }

    // Get by upperleft
    else {
        osCommand.Printf("select st_band(%s, %d) from %s.%s where "
            "abs(ST_UpperLeftX(%s) - %.8f) < 1e-8 and abs(ST_UpperLeftY(%s) - %.8f) < 1e-8",
            poRTDS->poRDS->pszColumn, nBand, poRTDS->poRDS->pszSchema, poRTDS->poRDS->pszTable, poRTDS->poRDS->pszColumn,
            poRTDS->adfGeoTransform[GEOTRSFRM_TOPLEFT_X], poRTDS->poRDS->pszColumn,
            poRTDS->adfGeoTransform[GEOTRSFRM_TOPLEFT_Y]);
    }

    poResult = PQexec(poRTDS->poRDS->poConn, osCommand.c_str());

#ifdef DEBUG_QUERY
    CPLDebug("PostGIS_Raster", "PostGISRasterTileRasterBand::IReadBlock(): "
             "Query = \"%s\" --> number of rows = %d",
             osCommand.c_str(), poResult ? PQntuples(poResult) : 0 );
#endif

    if (poResult == NULL ||
        PQresultStatus(poResult) != PGRES_TUPLES_OK ||
        PQntuples(poResult) <= 0) {

        if (poResult)
            PQclear(poResult);

        ReportError(CE_Failure, CPLE_AppDefined,
            "Error getting block of data (upperpixel = %f, %f)",
                poRTDS->adfGeoTransform[GEOTRSFRM_TOPLEFT_X],
                poRTDS->adfGeoTransform[GEOTRSFRM_TOPLEFT_Y]);

        return CE_Failure;
    }


    // TODO: Check this
    if (bIsOffline) {
        CPLError(CE_Failure, CPLE_AppDefined, "This raster has outdb "
            "storage. This feature isn't still available");

        PQclear(poResult);
        return CE_Failure;
    }

    /* Copy only data size, without payload */
    int nExpectedDataSize =
        nBlockXSize * nBlockYSize * nPixelSize;

    GByte * pbyData = CPLHexToBinary(PQgetvalue(poResult, 0, 0),
        &nWKBLength);
    int nExpectedWKBLength = RASTER_HEADER_SIZE + BAND_SIZE(nPixelSize, nExpectedDataSize);
    CPLErr eRet = CE_None;
    if( nWKBLength != nExpectedWKBLength )
    {
        CPLDebug("PostGIS_Raster", "nWKBLength=%d, nExpectedWKBLength=%d", nWKBLength, nExpectedWKBLength );
        eRet = CE_Failure;
    }
    else
    {
        GByte * pbyDataToRead =
        (GByte*)GET_BAND_DATA(pbyData,1, nPixelSize,
            nExpectedDataSize);

        // Do byte-swapping if necessary */
        int bIsLittleEndian = (pbyData[0] == 1);
#ifdef CPL_LSB
        int bSwap = !bIsLittleEndian;
#else
        int bSwap = bIsLittleEndian;
#endif
        if( bSwap && nPixelSize > 1 )
        {
            GDALSwapWords( pbyDataToRead, nPixelSize,
                           nBlockXSize * nBlockYSize,
                           nPixelSize );
        }

        memcpy(pImage, pbyDataToRead, nExpectedDataSize);
    }

    CPLFree(pbyData);
    PQclear(poResult);

    return eRet;
}
Пример #8
0
int pgQueryThread::execute()
{
	rowsInserted = -1L;

	if (!conn->conn)
		return(raiseEvent(0));

	wxCharBuffer queryBuf = query.mb_str(*conn->conv);
	if (!queryBuf && !query.IsEmpty())
	{
		conn->SetLastResultError(NULL, _("The query could not be converted to the required encoding."));
		return(raiseEvent(0));
	}

	if (!PQsendQuery(conn->conn, queryBuf))
	{
		conn->SetLastResultError(NULL);
		conn->IsAlive();
		return(raiseEvent(0));
	}
	int resultsRetrieved = 0;
	PGresult *lastResult = 0;
	while (true)
	{
		if (TestDestroy())
		{
			if (rc != -3)
			{
				if (!PQrequestCancel(conn->conn)) // could not abort; abort failed.
					return(raiseEvent(-1));

				rc = -3;
			}
		}
		if (!PQconsumeInput(conn->conn))
			return(raiseEvent(0));
		if (PQisBusy(conn->conn))
		{
			Yield();
			this->Sleep(10);
			continue;
		}

		// If resultToRetrieve is given, the nth result will be returned,
		// otherwise the last result set will be returned.
		// all others are discarded
		PGresult *res = PQgetResult(conn->conn);

		if (!res)
			break;

		resultsRetrieved++;
		if (resultsRetrieved == resultToRetrieve)
		{
			result = res;
			insertedOid = PQoidValue(res);
			if (insertedOid && insertedOid != (OID) - 1)
				appendMessage(wxString::Format(_("Query inserted one row with OID %d.\n"), insertedOid));
			else
				appendMessage(wxString::Format(wxPLURAL("Query result with %d row will be returned.\n", "Query result with %d rows will be returned.\n",
				                                        PQntuples(result)), PQntuples(result)));
			continue;
		}
		if (lastResult)
		{
			if (PQntuples(lastResult))
				appendMessage(wxString::Format(wxPLURAL("Query result with %d row discarded.\n", "Query result with %d rows discarded.\n",
				                                        PQntuples(lastResult)), PQntuples(lastResult)));
			PQclear(lastResult);
		}
		lastResult = res;
	}

	if (!result)
		result = lastResult;

	conn->SetLastResultError(result);

	appendMessage(wxT("\n"));
	rc = PQresultStatus(result);
	insertedOid = PQoidValue(result);
	if (insertedOid == (OID) - 1)
		insertedOid = 0;

	if (rc == PGRES_TUPLES_OK)
	{
		dataSet = new pgSet(result, conn, *conn->conv, conn->needColQuoting);
		dataSet->MoveFirst();
	}
	else if (rc == PGRES_COMMAND_OK)
	{
		char *s = PQcmdTuples(result);
		if (*s)
			rowsInserted = atol(s);
	}
	else if (rc == PGRES_FATAL_ERROR)
	{
		appendMessage(conn->GetLastError() + wxT("\n"));
	}
	return(raiseEvent(1));
}
Пример #9
0
KCSQLResult* PgSQLConnection::ExecuteQueryEx(
    const char* queryStr,
    long iTimeout,
    int type
)
{
    CMutexGuard		guard(m_MutexQuery);

    if (m_iAutoConnect)
    {
        if (m_conn)
        {
            if ( PQstatus(m_conn) == CONNECTION_BAD )
            {
                PQreset(m_conn);
                // 重试一次不行,就关闭该连接
                if (PQstatus(m_conn) == CONNECTION_BAD)
                {
                    PQfinish(m_conn);
                    m_conn = NULL;
                }
            }
        }

        if (m_conn == NULL)
        {
            if ( !Connect(iTimeout) )
            {
                return	new PgSQLResult(-1, "连接出错");
            }
        }
    }

    if (m_conn == NULL)
    {
        return	new PgSQLResult(-1, "无数据库连接");
    }

    PGresult* result = PQexec(m_conn, queryStr);
    if (result == NULL)
    {
        // 重试
        Connect(iTimeout);
        result = PQexec(m_conn, queryStr);
    }

    if (result == NULL)
    {
        return	NULL;
    }

    ExecStatusType resultInfo = PQresultStatus(result);
    m_errorCode = resultInfo;

    switch (resultInfo)
    {
    case PGRES_COMMAND_OK:
        // 仅记录影响行数
        return	new PgSQLResult( PQcmdTuples(result) ? atoi(PQcmdTuples(result)) : 0 );
        break;
    case PGRES_TUPLES_OK:
        return	new PgSQLResult(this, result);
        break;

    default:
        return new PgSQLResult(resultInfo, PQresultErrorMessage(result));
        break;
    }
}
Пример #10
0
static void
BaseBackup(void)
{
	PGresult   *res;
	char	   *sysidentifier;
	uint32		timeline;
	char		current_path[MAXPGPATH];
	char		escaped_label[MAXPGPATH];
	int			i;
	char		xlogstart[64];
	char		xlogend[64];

	/*
	 * Connect in replication mode to the server
	 */
	conn = GetConnection();

	/*
	 * Run IDENTIFY_SYSTEM so we can get the timeline
	 */
	res = PQexec(conn, "IDENTIFY_SYSTEM");
	if (PQresultStatus(res) != PGRES_TUPLES_OK)
	{
		fprintf(stderr, _("%s: could not identify system: %s\n"),
				progname, PQerrorMessage(conn));
		disconnect_and_exit(1);
	}
	if (PQntuples(res) != 1 || PQnfields(res) != 3)
	{
		fprintf(stderr, _("%s: could not identify system, got %i rows and %i fields\n"),
				progname, PQntuples(res), PQnfields(res));
		disconnect_and_exit(1);
	}
	sysidentifier = strdup(PQgetvalue(res, 0, 0));
	timeline = atoi(PQgetvalue(res, 0, 1));
	PQclear(res);

	/*
	 * Start the actual backup
	 */
	PQescapeStringConn(conn, escaped_label, label, sizeof(escaped_label), &i);
	snprintf(current_path, sizeof(current_path), "BASE_BACKUP LABEL '%s' %s %s %s %s",
			 escaped_label,
			 showprogress ? "PROGRESS" : "",
			 includewal && !streamwal ? "WAL" : "",
			 fastcheckpoint ? "FAST" : "",
			 includewal ? "NOWAIT" : "");

	if (PQsendQuery(conn, current_path) == 0)
	{
		fprintf(stderr, _("%s: could not send base backup command: %s"),
				progname, PQerrorMessage(conn));
		disconnect_and_exit(1);
	}

	/*
	 * Get the starting xlog position
	 */
	res = PQgetResult(conn);
	if (PQresultStatus(res) != PGRES_TUPLES_OK)
	{
		fprintf(stderr, _("%s: could not initiate base backup: %s"),
				progname, PQerrorMessage(conn));
		disconnect_and_exit(1);
	}
	if (PQntuples(res) != 1)
	{
		fprintf(stderr, _("%s: no start point returned from server\n"),
				progname);
		disconnect_and_exit(1);
	}
	strcpy(xlogstart, PQgetvalue(res, 0, 0));
	if (verbose && includewal)
		fprintf(stderr, "xlog start point: %s\n", xlogstart);
	PQclear(res);
	MemSet(xlogend, 0, sizeof(xlogend));

	/*
	 * Get the header
	 */
	res = PQgetResult(conn);
	if (PQresultStatus(res) != PGRES_TUPLES_OK)
	{
		fprintf(stderr, _("%s: could not get backup header: %s"),
				progname, PQerrorMessage(conn));
		disconnect_and_exit(1);
	}
	if (PQntuples(res) < 1)
	{
		fprintf(stderr, _("%s: no data returned from server\n"), progname);
		disconnect_and_exit(1);
	}

	/*
	 * Sum up the total size, for progress reporting
	 */
	totalsize = totaldone = 0;
	tablespacecount = PQntuples(res);
	for (i = 0; i < PQntuples(res); i++)
	{
		if (showprogress)
			totalsize += atol(PQgetvalue(res, i, 2));

		/*
		 * Verify tablespace directories are empty. Don't bother with the
		 * first once since it can be relocated, and it will be checked before
		 * we do anything anyway.
		 */
		if (format == 'p' && !PQgetisnull(res, i, 1))
			verify_dir_is_empty_or_create(PQgetvalue(res, i, 1));
	}

	/*
	 * When writing to stdout, require a single tablespace
	 */
	if (format == 't' && strcmp(basedir, "-") == 0 && PQntuples(res) > 1)
	{
		fprintf(stderr, _("%s: can only write single tablespace to stdout, database has %d\n"),
				progname, PQntuples(res));
		disconnect_and_exit(1);
	}

	/*
	 * If we're streaming WAL, start the streaming session before we start
	 * receiving the actual data chunks.
	 */
	if (streamwal)
	{
		if (verbose)
			fprintf(stderr, _("%s: starting background WAL receiver\n"),
					progname);
		StartLogStreamer(xlogstart, timeline, sysidentifier);
	}

	/*
	 * Start receiving chunks
	 */
	for (i = 0; i < PQntuples(res); i++)
	{
		if (format == 't')
			ReceiveTarFile(conn, res, i);
		else
			ReceiveAndUnpackTarFile(conn, res, i);
	}							/* Loop over all tablespaces */

	if (showprogress)
	{
		progress_report(PQntuples(res), NULL);
		fprintf(stderr, "\n");	/* Need to move to next line */
	}
	PQclear(res);

	/*
	 * Get the stop position
	 */
	res = PQgetResult(conn);
	if (PQresultStatus(res) != PGRES_TUPLES_OK)
	{
		fprintf(stderr, _("%s: could not get WAL end position from server\n"),
				progname);
		disconnect_and_exit(1);
	}
	if (PQntuples(res) != 1)
	{
		fprintf(stderr, _("%s: no WAL end position returned from server\n"),
				progname);
		disconnect_and_exit(1);
	}
	strcpy(xlogend, PQgetvalue(res, 0, 0));
	if (verbose && includewal)
		fprintf(stderr, "xlog end point: %s\n", xlogend);
	PQclear(res);

	res = PQgetResult(conn);
	if (PQresultStatus(res) != PGRES_COMMAND_OK)
	{
		fprintf(stderr, _("%s: final receive failed: %s"),
				progname, PQerrorMessage(conn));
		disconnect_and_exit(1);
	}

	if (bgchild > 0)
	{
#ifndef WIN32
		int			status;
		int			r;
#else
		DWORD       status;
#endif

		if (verbose)
			fprintf(stderr, _("%s: waiting for background process to finish streaming...\n"), progname);

#ifndef WIN32
		if (pipewrite(bgpipe[1], xlogend, strlen(xlogend)) != strlen(xlogend))
		{
			fprintf(stderr, _("%s: could not send command to background pipe: %s\n"),
					progname, strerror(errno));
			disconnect_and_exit(1);
		}

		/* Just wait for the background process to exit */
		r = waitpid(bgchild, &status, 0);
		if (r == -1)
		{
			fprintf(stderr, _("%s: could not wait for child process: %s\n"),
					progname, strerror(errno));
			disconnect_and_exit(1);
		}
		if (r != bgchild)
		{
			fprintf(stderr, _("%s: child %i died, expected %i\n"),
					progname, r, bgchild);
			disconnect_and_exit(1);
		}
		if (!WIFEXITED(status))
		{
			fprintf(stderr, _("%s: child process did not exit normally\n"),
					progname);
			disconnect_and_exit(1);
		}
		if (WEXITSTATUS(status) != 0)
		{
			fprintf(stderr, _("%s: child process exited with error %i\n"),
					progname, WEXITSTATUS(status));
			disconnect_and_exit(1);
		}
		/* Exited normally, we're happy! */
#else							/* WIN32 */

		/*
		 * On Windows, since we are in the same process, we can just store the
		 * value directly in the variable, and then set the flag that says
		 * it's there.
		 */
		if (sscanf(xlogend, "%X/%X", &xlogendptr.xlogid, &xlogendptr.xrecoff) != 2)
		{
			fprintf(stderr, _("%s: could not parse xlog end position \"%s\"\n"),
					progname, xlogend);
			disconnect_and_exit(1);
		}
		InterlockedIncrement(&has_xlogendptr);

		/* First wait for the thread to exit */
		if (WaitForSingleObjectEx((HANDLE) bgchild, INFINITE, FALSE) != WAIT_OBJECT_0)
		{
			_dosmaperr(GetLastError());
			fprintf(stderr, _("%s: could not wait for child thread: %s\n"),
					progname, strerror(errno));
			disconnect_and_exit(1);
		}
		if (GetExitCodeThread((HANDLE) bgchild, &status) == 0)
		{
			_dosmaperr(GetLastError());
			fprintf(stderr, _("%s: could not get child thread exit status: %s\n"),
					progname, strerror(errno));
			disconnect_and_exit(1);
		}
		if (status != 0)
		{
			fprintf(stderr, _("%s: child thread exited with error %u\n"),
					progname, (unsigned int) status);
			disconnect_and_exit(1);
		}
		/* Exited normally, we're happy */
#endif
	}

	/*
	 * End of copy data. Final result is already checked inside the loop.
	 */
	PQclear(res);
	PQfinish(conn);

	if (verbose)
		fprintf(stderr, "%s: base backup completed\n", progname);
}
Пример #11
0
void Plugin::saveValue(const char *tagname, const char *tablename, const char *valstring)
{
#ifdef WITHDB
  PGconn *conn = NULL;

  TObject *dummy=getMemoryObject("Runnumber");
  int runnumber=htonl(*(int*) &dummy); //ugly but works 
  // Make a connection to the database
  conn = PQconnectdb("user=runinfo password=runinfo dbname=runinfo host=CookerWorkerNodeLNS00");
  
  // Check to see that the backend connection was successfully made
  if (PQstatus(conn) != CONNECTION_OK)
    {
      debug(0,"Connection to database failed\n");
      PQfinish(conn);
      return ;
    }
  const char *params[]={tagname,(char *) &runnumber,valstring};

  int lengths[3]={strlen(tagname),sizeof(runnumber),strlen(valstring)};
  int binary[3]={0,1,0};
  debug(100,"Connection to database - OK\n");
  PGresult *res=PQexecParams(conn, "select tagid from tagnames where tagname=$1::varchar;",1,NULL,params,lengths,binary,0);
  if (PQresultStatus(res) != PGRES_TUPLES_OK)
    {
      debug(0, "select tagid command failed: %s\n", PQerrorMessage(conn));
      PQclear(res);
      PQfinish(conn);
      return;
    }
  debug(100,"Found %i\n",PQntuples(res));
  if (PQntuples(res)==0)
    {
      PQclear(res);
      debug(100,"Trying to insert\n");
      res=PQexecParams(conn, "insert into tagnames  (tagname) values ($1::varchar);",1,NULL,params,lengths,binary,0);
      if (PQresultStatus(res) != PGRES_COMMAND_OK)
	{
	  debug(0, "insert into tagid command failed: %s\n", PQerrorMessage(conn));
	  PQclear(res);
	  PQfinish(conn);
	  return;
	}
    }
  PQclear(res);
  debug(100,"Trying to insert\n");
  char command[1000];
  sprintf(command,"insert into %s (timestamp,runid,tagid,value) select now(),$2::int4,tagid,$3::double precision from tagnames where tagname=$1::varchar;",tablename);
  res=PQexecParams(conn, command,3,NULL,params,lengths,binary,0);
  if (PQresultStatus(res) != PGRES_COMMAND_OK)
    {
      debug(100, "insert into rundata command failed: %s\n Trying update", PQerrorMessage(conn));
      PQclear(res);
      sprintf(command,"update %s set timestamp=now(), value=$3::double precision where runid=$2::int4 and tagid=(select tagid from tagnames where tagname=$1::varchar);",tablename);
      res=PQexecParams(conn, command,3,NULL,params,lengths,binary,0);
      if (PQresultStatus(res) != PGRES_COMMAND_OK)
	{
	  debug(100, "update failed too: %s\n", PQerrorMessage(conn));
	  PQclear(res);
	  PQfinish(conn);
	  return;
	}
    }
  PQclear(res);
  
  PQfinish(conn);
#else
  debug(10000,"DB not compiled in\n");
#endif
}
Пример #12
0
/*
 * Receive a tar format stream from the connection to the server, and unpack
 * the contents of it into a directory. Only files, directories and
 * symlinks are supported, no other kinds of special files.
 *
 * If the data is for the main data directory, it will be restored in the
 * specified directory. If it's for another tablespace, it will be restored
 * in the original directory, since relocation of tablespaces is not
 * supported.
 */
static void
ReceiveAndUnpackTarFile(PGconn *conn, PGresult *res, int rownum)
{
	char		current_path[MAXPGPATH];
	char		filename[MAXPGPATH];
	int			current_len_left;
	int			current_padding = 0;
	char	   *copybuf = NULL;
	FILE	   *file = NULL;

	if (PQgetisnull(res, rownum, 0))
		strcpy(current_path, basedir);
	else
		strcpy(current_path, PQgetvalue(res, rownum, 1));

	/*
	 * Get the COPY data
	 */
	res = PQgetResult(conn);
	if (PQresultStatus(res) != PGRES_COPY_OUT)
	{
		fprintf(stderr, _("%s: could not get COPY data stream: %s"),
				progname, PQerrorMessage(conn));
		disconnect_and_exit(1);
	}

	while (1)
	{
		int			r;

		if (copybuf != NULL)
		{
			PQfreemem(copybuf);
			copybuf = NULL;
		}

		r = PQgetCopyData(conn, &copybuf, 0);

		if (r == -1)
		{
			/*
			 * End of chunk
			 */
			if (file)
				fclose(file);

			break;
		}
		else if (r == -2)
		{
			fprintf(stderr, _("%s: could not read COPY data: %s"),
					progname, PQerrorMessage(conn));
			disconnect_and_exit(1);
		}

		if (file == NULL)
		{
			int			filemode;

			/*
			 * No current file, so this must be the header for a new file
			 */
			if (r != 512)
			{
				fprintf(stderr, _("%s: invalid tar block header size: %d\n"),
						progname, r);
				disconnect_and_exit(1);
			}
			totaldone += 512;

			if (sscanf(copybuf + 124, "%11o", &current_len_left) != 1)
			{
				fprintf(stderr, _("%s: could not parse file size\n"),
						progname);
				disconnect_and_exit(1);
			}

			/* Set permissions on the file */
			if (sscanf(&copybuf[100], "%07o ", &filemode) != 1)
			{
				fprintf(stderr, _("%s: could not parse file mode\n"),
						progname);
				disconnect_and_exit(1);
			}

			/*
			 * All files are padded up to 512 bytes
			 */
			current_padding =
				((current_len_left + 511) & ~511) - current_len_left;

			/*
			 * First part of header is zero terminated filename
			 */
			snprintf(filename, sizeof(filename), "%s/%s", current_path, copybuf);
			if (filename[strlen(filename) - 1] == '/')
			{
				/*
				 * Ends in a slash means directory or symlink to directory
				 */
				if (copybuf[156] == '5')
				{
					/*
					 * Directory
					 */
					filename[strlen(filename) - 1] = '\0';		/* Remove trailing slash */
					if (mkdir(filename, S_IRWXU) != 0)
					{
						/*
						 * When streaming WAL, pg_xlog will have been created
						 * by the wal receiver process, so just ignore failure
						 * on that.
						 */
						if (!streamwal || strcmp(filename + strlen(filename) - 8, "/pg_xlog") != 0)
						{
							fprintf(stderr,
							_("%s: could not create directory \"%s\": %s\n"),
									progname, filename, strerror(errno));
							disconnect_and_exit(1);
						}
					}
#ifndef WIN32
					if (chmod(filename, (mode_t) filemode))
						fprintf(stderr, _("%s: could not set permissions on directory \"%s\": %s\n"),
								progname, filename, strerror(errno));
#endif
				}
				else if (copybuf[156] == '2')
				{
					/*
					 * Symbolic link
					 */
					filename[strlen(filename) - 1] = '\0';		/* Remove trailing slash */
					if (symlink(&copybuf[157], filename) != 0)
					{
						fprintf(stderr,
								_("%s: could not create symbolic link from \"%s\" to \"%s\": %s\n"),
						 progname, filename, &copybuf[157], strerror(errno));
						disconnect_and_exit(1);
					}
				}
				else
				{
					fprintf(stderr, _("%s: unrecognized link indicator \"%c\"\n"),
							progname, copybuf[156]);
					disconnect_and_exit(1);
				}
				continue;		/* directory or link handled */
			}

			/*
			 * regular file
			 */
			file = fopen(filename, "wb");
			if (!file)
			{
				fprintf(stderr, _("%s: could not create file \"%s\": %s\n"),
						progname, filename, strerror(errno));
				disconnect_and_exit(1);
			}

#ifndef WIN32
			if (chmod(filename, (mode_t) filemode))
				fprintf(stderr, _("%s: could not set permissions on file \"%s\": %s\n"),
						progname, filename, strerror(errno));
#endif

			if (current_len_left == 0)
			{
				/*
				 * Done with this file, next one will be a new tar header
				 */
				fclose(file);
				file = NULL;
				continue;
			}
		}						/* new file */
		else
		{
			/*
			 * Continuing blocks in existing file
			 */
			if (current_len_left == 0 && r == current_padding)
			{
				/*
				 * Received the padding block for this file, ignore it and
				 * close the file, then move on to the next tar header.
				 */
				fclose(file);
				file = NULL;
				totaldone += r;
				continue;
			}

			if (fwrite(copybuf, r, 1, file) != 1)
			{
				fprintf(stderr, _("%s: could not write to file \"%s\": %s\n"),
						progname, filename, strerror(errno));
				disconnect_and_exit(1);
			}
			totaldone += r;
			if (showprogress)
				progress_report(rownum, filename);

			current_len_left -= r;
			if (current_len_left == 0 && current_padding == 0)
			{
				/*
				 * Received the last block, and there is no padding to be
				 * expected. Close the file and move on to the next tar
				 * header.
				 */
				fclose(file);
				file = NULL;
				continue;
			}
		}						/* continuing data in existing file */
	}							/* loop over all data blocks */

	if (file != NULL)
	{
		fprintf(stderr, _("%s: COPY stream ended before last file was finished\n"), progname);
		disconnect_and_exit(1);
	}

	if (copybuf != NULL)
		PQfreemem(copybuf);
}
Пример #13
0
/*
 * Receive a tar format file from the connection to the server, and write
 * the data from this file directly into a tar file. If compression is
 * enabled, the data will be compressed while written to the file.
 *
 * The file will be named base.tar[.gz] if it's for the main data directory
 * or <tablespaceoid>.tar[.gz] if it's for another tablespace.
 *
 * No attempt to inspect or validate the contents of the file is done.
 */
static void
ReceiveTarFile(PGconn *conn, PGresult *res, int rownum)
{
	char		filename[MAXPGPATH];
	char	   *copybuf = NULL;
	FILE	   *tarfile = NULL;

#ifdef HAVE_LIBZ
	gzFile		ztarfile = NULL;
#endif

	if (PQgetisnull(res, rownum, 0))

		/*
		 * Base tablespaces
		 */
		if (strcmp(basedir, "-") == 0)
		{
#ifdef HAVE_LIBZ
			if (compresslevel != 0)
			{
				ztarfile = gzdopen(dup(fileno(stdout)), "wb");
				if (gzsetparams(ztarfile, compresslevel, Z_DEFAULT_STRATEGY) != Z_OK)
				{
					fprintf(stderr, _("%s: could not set compression level %d: %s\n"),
							progname, compresslevel, get_gz_error(ztarfile));
					disconnect_and_exit(1);
				}
			}
			else
#endif
				tarfile = stdout;
		}
		else
		{
#ifdef HAVE_LIBZ
			if (compresslevel != 0)
			{
				snprintf(filename, sizeof(filename), "%s/base.tar.gz", basedir);
				ztarfile = gzopen(filename, "wb");
				if (gzsetparams(ztarfile, compresslevel, Z_DEFAULT_STRATEGY) != Z_OK)
				{
					fprintf(stderr, _("%s: could not set compression level %d: %s\n"),
							progname, compresslevel, get_gz_error(ztarfile));
					disconnect_and_exit(1);
				}
			}
			else
#endif
			{
				snprintf(filename, sizeof(filename), "%s/base.tar", basedir);
				tarfile = fopen(filename, "wb");
			}
		}
	else
	{
		/*
		 * Specific tablespace
		 */
#ifdef HAVE_LIBZ
		if (compresslevel != 0)
		{
			snprintf(filename, sizeof(filename), "%s/%s.tar.gz", basedir, PQgetvalue(res, rownum, 0));
			ztarfile = gzopen(filename, "wb");
			if (gzsetparams(ztarfile, compresslevel, Z_DEFAULT_STRATEGY) != Z_OK)
			{
				fprintf(stderr, _("%s: could not set compression level %d: %s\n"),
						progname, compresslevel, get_gz_error(ztarfile));
				disconnect_and_exit(1);
			}
		}
		else
#endif
		{
			snprintf(filename, sizeof(filename), "%s/%s.tar", basedir, PQgetvalue(res, rownum, 0));
			tarfile = fopen(filename, "wb");
		}
	}

#ifdef HAVE_LIBZ
	if (compresslevel != 0)
	{
		if (!ztarfile)
		{
			/* Compression is in use */
			fprintf(stderr, _("%s: could not create compressed file \"%s\": %s\n"),
					progname, filename, get_gz_error(ztarfile));
			disconnect_and_exit(1);
		}
	}
	else
#endif
	{
		/* Either no zlib support, or zlib support but compresslevel = 0 */
		if (!tarfile)
		{
			fprintf(stderr, _("%s: could not create file \"%s\": %s\n"),
					progname, filename, strerror(errno));
			disconnect_and_exit(1);
		}
	}

	/*
	 * Get the COPY data stream
	 */
	res = PQgetResult(conn);
	if (PQresultStatus(res) != PGRES_COPY_OUT)
	{
		fprintf(stderr, _("%s: could not get COPY data stream: %s"),
				progname, PQerrorMessage(conn));
		disconnect_and_exit(1);
	}

	while (1)
	{
		int			r;

		if (copybuf != NULL)
		{
			PQfreemem(copybuf);
			copybuf = NULL;
		}

		r = PQgetCopyData(conn, &copybuf, 0);
		if (r == -1)
		{
			/*
			 * End of chunk. Close file (but not stdout).
			 *
			 * Also, write two completely empty blocks at the end of the tar
			 * file, as required by some tar programs.
			 */
			char		zerobuf[1024];

			MemSet(zerobuf, 0, sizeof(zerobuf));
#ifdef HAVE_LIBZ
			if (ztarfile != NULL)
			{
				if (gzwrite(ztarfile, zerobuf, sizeof(zerobuf)) != sizeof(zerobuf))
				{
					fprintf(stderr, _("%s: could not write to compressed file \"%s\": %s\n"),
							progname, filename, get_gz_error(ztarfile));
				}
			}
			else
#endif
			{
				if (fwrite(zerobuf, sizeof(zerobuf), 1, tarfile) != 1)
				{
					fprintf(stderr, _("%s: could not write to file \"%s\": %s\n"),
							progname, filename, strerror(errno));
					disconnect_and_exit(1);
				}
			}

			if (strcmp(basedir, "-") == 0)
			{
#ifdef HAVE_LIBZ
				if (ztarfile)
					gzclose(ztarfile);
#endif
			}
			else
			{
#ifdef HAVE_LIBZ
				if (ztarfile != NULL)
					gzclose(ztarfile);
#endif
				if (tarfile != NULL)
					fclose(tarfile);
			}

			break;
		}
		else if (r == -2)
		{
			fprintf(stderr, _("%s: could not read COPY data: %s"),
					progname, PQerrorMessage(conn));
			disconnect_and_exit(1);
		}

#ifdef HAVE_LIBZ
		if (ztarfile != NULL)
		{
			if (gzwrite(ztarfile, copybuf, r) != r)
			{
				fprintf(stderr, _("%s: could not write to compressed file \"%s\": %s\n"),
						progname, filename, get_gz_error(ztarfile));
			}
		}
		else
#endif
		{
			if (fwrite(copybuf, r, 1, tarfile) != 1)
			{
				fprintf(stderr, _("%s: could not write to file \"%s\": %s\n"),
						progname, filename, strerror(errno));
				disconnect_and_exit(1);
			}
		}
		totaldone += r;
		if (showprogress)
			progress_report(rownum, filename);
	}							/* while (1) */

	if (copybuf != NULL)
		PQfreemem(copybuf);
}
Пример #14
0
/******************************************************************************
 *                                                                            *
 * Function: zbx_db_vselect                                                   *
 *                                                                            *
 * Purpose: execute a select statement                                        *
 *                                                                            *
 * Return value: data, NULL (on error) or (DB_RESULT)ZBX_DB_DOWN              *
 *                                                                            *
 ******************************************************************************/
DB_RESULT	zbx_db_vselect(const char *fmt, va_list args)
{
	char		*sql = NULL;
	DB_RESULT	result = NULL;
	double		sec = 0;

#if defined(HAVE_IBM_DB2)
	int		i;
	SQLRETURN	ret = SQL_SUCCESS;
#elif defined(HAVE_ORACLE)
	sword		err = OCI_SUCCESS;
	ub4		counter;
#elif defined(HAVE_POSTGRESQL)
	char		*error = NULL;
#elif defined(HAVE_SQLITE3)
	int		ret = FAIL;
	char		*error = NULL;
#endif

	if (CONFIG_LOG_SLOW_QUERIES)
		sec = zbx_time();

	sql = zbx_dvsprintf(sql, fmt, args);

	zabbix_log(LOG_LEVEL_DEBUG, "query [txnlev:%d] [%s]", txn_level, sql);

#if defined(HAVE_IBM_DB2)
	result = zbx_malloc(result, sizeof(ZBX_IBM_DB2_RESULT));
	memset(result, 0, sizeof(ZBX_IBM_DB2_RESULT));

	/* allocate a statement handle */
	if (SUCCEED != zbx_ibm_db2_success(ret = SQLAllocHandle(SQL_HANDLE_STMT, ibm_db2.hdbc, &result->hstmt)))
		goto error;

	/* directly execute the statement */
	if (SUCCEED != zbx_ibm_db2_success(ret = SQLExecDirect(result->hstmt, (SQLCHAR *)sql, SQL_NTS)))
		goto error;

	/* identify the number of output columns */
	if (SUCCEED != zbx_ibm_db2_success(ret = SQLNumResultCols(result->hstmt, &result->ncolumn)))
		goto error;

	if (0 == result->ncolumn)
		goto error;

	result->nalloc = 0;
	result->values = zbx_malloc(result->values, sizeof(char *) * result->ncolumn);
	result->values_cli = zbx_malloc(result->values_cli, sizeof(char *) * result->ncolumn);
	result->values_len = zbx_malloc(result->values_len, sizeof(SQLINTEGER) * result->ncolumn);

	for (i = 0; i < result->ncolumn; i++)
	{
		/* get the display size for a column */
		if (SUCCEED != zbx_ibm_db2_success(ret = SQLColAttribute(result->hstmt, (SQLSMALLINT)(i + 1),
				SQL_DESC_DISPLAY_SIZE, NULL, 0, NULL, &result->values_len[i])))
		{
			goto error;
		}

		result->values_len[i] += 1; /* '\0'; */

		/* allocate memory to bind a column */
		result->values_cli[i] = zbx_malloc(NULL, result->values_len[i]);
		result->nalloc++;

		/* bind columns to program variables, converting all types to CHAR */
		if (SUCCEED != zbx_ibm_db2_success(ret = SQLBindCol(result->hstmt, (SQLSMALLINT)(i + 1),
				SQL_C_CHAR, result->values_cli[i], result->values_len[i], &result->values_len[i])))
		{
			goto error;
		}
	}
error:
	if (SUCCEED != zbx_ibm_db2_success(ret) || 0 == result->ncolumn)
	{
		zbx_ibm_db2_log_errors(SQL_HANDLE_DBC, ibm_db2.hdbc);
		zbx_ibm_db2_log_errors(SQL_HANDLE_STMT, result->hstmt);

		IBM_DB2free_result(result);

		result = (SQL_CD_TRUE == IBM_DB2server_status() ? NULL : (DB_RESULT)ZBX_DB_DOWN);
	}
#elif defined(HAVE_MYSQL)
	if (NULL == conn)
	{
		zabbix_errlog(ERR_Z3003);
		result = NULL;
	}
	else
	{
		if (0 != mysql_query(conn, sql))
		{
			zabbix_errlog(ERR_Z3005, mysql_errno(conn), mysql_error(conn), sql);
			switch (mysql_errno(conn))
			{
				case CR_CONN_HOST_ERROR:
				case CR_SERVER_GONE_ERROR:
				case CR_CONNECTION_ERROR:
				case CR_SERVER_LOST:
				case ER_SERVER_SHUTDOWN:
				case ER_ACCESS_DENIED_ERROR: /* wrong user or password */
				case ER_ILLEGAL_GRANT_FOR_TABLE: /* user without any privileges */
				case ER_TABLEACCESS_DENIED_ERROR:/* user without some privilege */
				case ER_UNKNOWN_ERROR:
					result = (DB_RESULT)ZBX_DB_DOWN;
					break;
				default:
					result = NULL;
					break;
			}
		}
		else
			result = mysql_store_result(conn);
	}
#elif defined(HAVE_ORACLE)
	result = zbx_malloc(NULL, sizeof(ZBX_OCI_DB_RESULT));
	memset(result, 0, sizeof(ZBX_OCI_DB_RESULT));

	err = OCIHandleAlloc((dvoid *)oracle.envhp, (dvoid **)&result->stmthp, OCI_HTYPE_STMT, (size_t)0, (dvoid **)0);

	if (OCI_SUCCESS == err)
	{
		err = OCIStmtPrepare(result->stmthp, oracle.errhp, (text *)sql, (ub4)strlen((char *)sql),
				(ub4)OCI_NTV_SYNTAX, (ub4)OCI_DEFAULT);
	}

	if (OCI_SUCCESS == err)
	{
		err = OCIStmtExecute(oracle.svchp, result->stmthp, oracle.errhp, (ub4)0, (ub4)0,
				(CONST OCISnapshot *)NULL, (OCISnapshot *)NULL, OCI_COMMIT_ON_SUCCESS);
	}

	if (OCI_SUCCESS == err)
	{
		/* get the number of columns in the query */
		err = OCIAttrGet((void *)result->stmthp, OCI_HTYPE_STMT, (void *)&result->ncolumn,
				  (ub4 *)0, OCI_ATTR_PARAM_COUNT, oracle.errhp);
	}

	if (OCI_SUCCESS != err)
		goto error;

	assert(0 < result->ncolumn);

	result->values = zbx_malloc(NULL, result->ncolumn * sizeof(char *));
	memset(result->values, 0, result->ncolumn * sizeof(char *));

	for (counter = 1; OCI_SUCCESS == err && counter <= result->ncolumn; counter++)
	{
		OCIParam	*parmdp = NULL;
		OCIDefine	*defnp = NULL;
		ub4		char_semantics;
		ub2		col_width;

		/* request a parameter descriptor in the select-list */
		err = OCIParamGet((void *)result->stmthp, OCI_HTYPE_STMT, oracle.errhp, (void **)&parmdp, (ub4)counter);

		if (OCI_SUCCESS == err)
		{
			/* retrieve the length semantics for the column */
			char_semantics = 0;
			err = OCIAttrGet((void *)parmdp, (ub4)OCI_DTYPE_PARAM, (void *)&char_semantics, (ub4 *)0,
					(ub4)OCI_ATTR_CHAR_USED, (OCIError *)oracle.errhp);
		}

		if (OCI_SUCCESS == err)
		{
			col_width = 0;
			if (char_semantics)
			{
				/* retrieve the column width in characters */
				err = OCIAttrGet((void *)parmdp, (ub4)OCI_DTYPE_PARAM, (void *)&col_width, (ub4 *)0,
						(ub4)OCI_ATTR_CHAR_SIZE, (OCIError *)oracle.errhp);
			}
			else
			{
				/* retrieve the column width in bytes */
				err = OCIAttrGet((void *)parmdp, (ub4)OCI_DTYPE_PARAM, (void *)&col_width, (ub4 *)0,
						(ub4)OCI_ATTR_DATA_SIZE, (OCIError *)oracle.errhp);
			}
		}
		col_width++;

		result->values[counter - 1] = zbx_malloc(NULL, col_width);
		memset(result->values[counter - 1], 0, col_width);

		if (OCI_SUCCESS == err)
		{
			/* represent any data as characters */
			err = OCIDefineByPos(result->stmthp, &defnp, oracle.errhp, counter,
					(dvoid *)result->values[counter - 1], col_width, SQLT_STR,
					(dvoid *)0, (ub2 *)0, (ub2 *)0, OCI_DEFAULT);
		}

		/* free cell descriptor */
		OCIDescriptorFree(parmdp, OCI_DTYPE_PARAM);
		parmdp = NULL;
	}

error:
	if (OCI_SUCCESS != err)
	{
		zabbix_errlog(ERR_Z3005, err, zbx_oci_error(err), sql);

		OCI_DBfree_result(result);

		result = (OCI_SERVER_NORMAL == OCI_DBserver_status() ? NULL : (DB_RESULT)ZBX_DB_DOWN);
	}
#elif defined(HAVE_POSTGRESQL)
	result = zbx_malloc(NULL, sizeof(ZBX_PG_DB_RESULT));
	result->pg_result = PQexec(conn, sql);
	result->values = NULL;
	result->cursor = 0;
	result->row_num = 0;

	if (NULL == result->pg_result)
		zabbix_errlog(ERR_Z3005, 0, "result is NULL", sql);

	if (PGRES_TUPLES_OK != PQresultStatus(result->pg_result))
	{
		error = zbx_dsprintf(error, "%s:%s",
				PQresStatus(PQresultStatus(result->pg_result)),
				PQresultErrorMessage(result->pg_result));
		zabbix_errlog(ERR_Z3005, 0, error, sql);
		zbx_free(error);

		PG_DBfree_result(result);
		result = (CONNECTION_OK == PQstatus(conn) ? NULL : (DB_RESULT)ZBX_DB_DOWN);
	}
	else	/* init rownum */
		result->row_num = PQntuples(result->pg_result);
#elif defined(HAVE_SQLITE3)
	if (0 == txn_level && PHP_MUTEX_OK != php_sem_acquire(&sqlite_access))
	{
		zabbix_log(LOG_LEVEL_CRIT, "ERROR: unable to create lock on SQLite database");
		exit(FAIL);
	}

	result = zbx_malloc(NULL, sizeof(ZBX_SQ_DB_RESULT));
	result->curow = 0;

lbl_get_table:
	if (SQLITE_OK != (ret = sqlite3_get_table(conn,sql, &result->data, &result->nrow, &result->ncolumn, &error)))
	{
		if (SQLITE_BUSY == ret)
			goto lbl_get_table;

		zabbix_errlog(ERR_Z3005, 0, error, sql);
		sqlite3_free(error);

		SQ_DBfree_result(result);

		switch (ret)
		{
			case SQLITE_ERROR:	/* SQL error or missing database; assuming SQL error, because if we
						   are this far into execution, zbx_db_connect() was successful */
			case SQLITE_NOMEM:	/* a malloc() failed */
			case SQLITE_MISMATCH:	/* data type mismatch */
				result = NULL;
				break;
			default:
				result = (DB_RESULT)ZBX_DB_DOWN;
				break;
		}
	}

	if (0 == txn_level)
		php_sem_release(&sqlite_access);
#endif	/* HAVE_SQLITE3 */

	if (CONFIG_LOG_SLOW_QUERIES)
	{
		sec = zbx_time() - sec;
		if (sec > (double)CONFIG_LOG_SLOW_QUERIES / 1000.0)
			zabbix_log(LOG_LEVEL_WARNING, "slow query: " ZBX_FS_DBL " sec, \"%s\"", sec, sql);
	}

	zbx_free(sql);
	return result;
}
/*************************************************************************
 *
 *	Function: sql_query
 *
 *	Purpose: Issue a query to the database
 *
 *************************************************************************/
static sql_rcode_t sql_query(rlm_sql_handle_t * handle, UNUSED rlm_sql_config_t *config, char const *query)
{
	rlm_sql_postgres_conn_t *conn = handle->conn;
	int numfields = 0;
	char *errorcode;
	char *errormsg;

	if (!conn->db) {
		ERROR("rlm_sql_postgresql: Socket not connected");
		return RLM_SQL_RECONNECT;
	}

	conn->result = PQexec(conn->db, query);
		/*
		 * Returns a PGresult pointer or possibly a null pointer.
		 * A non-null pointer will generally be returned except in
		 * out-of-memory conditions or serious errors such as inability
		 * to send the command to the server. If a null pointer is
		 * returned, it should be treated like a PGRES_FATAL_ERROR
		 * result.
		 */
	if (!conn->result)
	{
		ERROR("rlm_sql_postgresql: PostgreSQL Query failed Error: %s",
				PQerrorMessage(conn->db));
		/* As this error COULD be a connection error OR an out-of-memory
		 * condition return value WILL be wrong SOME of the time regardless!
		 * Pick your poison....
		 */
		return  RLM_SQL_RECONNECT;
	} else {
		ExecStatusType status = PQresultStatus(conn->result);
		DEBUG("rlm_sql_postgresql: Status: %s", PQresStatus(status));

		switch (status){

			case PGRES_COMMAND_OK:
				/*Successful completion of a command returning no data.*/

				/*affected_rows function only returns
				the number of affected rows of a command
				returning no data...
				*/
				conn->affected_rows	= affected_rows(conn->result);
				DEBUG("rlm_sql_postgresql: query affected rows = %i", conn->affected_rows);
				return 0;

			break;

			case PGRES_TUPLES_OK:
				/*Successful completion of a command returning data (such as a SELECT or SHOW).*/

				conn->cur_row = 0;
 				conn->affected_rows = PQntuples(conn->result);
				numfields = PQnfields(conn->result); /*Check row storing functions..*/
				DEBUG("rlm_sql_postgresql: query affected rows = %i , fields = %i", conn->affected_rows, numfields);
				return 0;

			break;

			case PGRES_BAD_RESPONSE:
				/*The server's response was not understood.*/
				DEBUG("rlm_sql_postgresql: Bad Response From Server!!");
				return -1;

			break;

			case PGRES_NONFATAL_ERROR:
				/*A nonfatal error (a notice or warning) occurred. Possibly never returns*/

				return -1;

			break;

			case PGRES_FATAL_ERROR:
#if defined(PG_DIAG_SQLSTATE) && defined(PG_DIAG_MESSAGE_PRIMARY)
				/*A fatal error occurred.*/

				errorcode = PQresultErrorField(conn->result, PG_DIAG_SQLSTATE);
				errormsg  = PQresultErrorField(conn->result, PG_DIAG_MESSAGE_PRIMARY);
				DEBUG("rlm_sql_postgresql: Error %s", errormsg);
				return check_fatal_error(errorcode);
#endif

			break;

			default:
				/* FIXME: An unhandled error occurred.*/

				/* PGRES_EMPTY_QUERY PGRES_COPY_OUT PGRES_COPY_IN */

				return -1;

			break;


		}

		/*
			Note to self ... sql_store_result returns 0 anyway
			after setting the handle->affected_rows..
			sql_num_fields returns 0 at worst case which means the check below
			has a really small chance to return false..
			lets remove it then .. yuck!!
		*/
		/*
		} else {
			if ((sql_store_result(handle, config) == 0)
					&& (sql_num_fields(handle, config) >= 0))
				return 0;
			else
				return -1;
		}
		*/
	}
	return -1;
}
Пример #16
0
/*
 * ExecQueryUsingCursor: run a SELECT-like query using a cursor
 *
 * This feature allows result sets larger than RAM to be dealt with.
 *
 * Returns true if the query executed successfully, false otherwise.
 *
 * If pset.timing is on, total query time (exclusive of result-printing) is
 * stored into *elapsed_msec.
 */
static bool
ExecQueryUsingCursor(const char *query, double *elapsed_msec)
{
	bool		OK = true;
	PGresult   *results;
	PQExpBufferData buf;
	printQueryOpt my_popt = pset.popt;
	FILE	   *queryFout_copy = pset.queryFout;
	bool		queryFoutPipe_copy = pset.queryFoutPipe;
	bool		started_txn = false;
	bool		did_pager = false;
	int			ntuples;
	int			fetch_count;
	char		fetch_cmd[64];
	instr_time	before,
				after;
	int			flush_error;

	*elapsed_msec = 0;

	/* initialize print options for partial table output */
	my_popt.topt.start_table = true;
	my_popt.topt.stop_table = false;
	my_popt.topt.prior_records = 0;

	if (pset.timing)
		INSTR_TIME_SET_CURRENT(before);

	/* if we're not in a transaction, start one */
	if (PQtransactionStatus(pset.db) == PQTRANS_IDLE)
	{
		results = PQexec(pset.db, "BEGIN");
		OK = AcceptResult(results) &&
			(PQresultStatus(results) == PGRES_COMMAND_OK);
		PQclear(results);
		if (!OK)
			return false;
		started_txn = true;
	}

	/* Send DECLARE CURSOR */
	initPQExpBuffer(&buf);
	appendPQExpBuffer(&buf, "DECLARE _psql_cursor NO SCROLL CURSOR FOR\n%s",
					  query);

	results = PQexec(pset.db, buf.data);
	OK = AcceptResult(results) &&
		(PQresultStatus(results) == PGRES_COMMAND_OK);
	PQclear(results);
	termPQExpBuffer(&buf);
	if (!OK)
		goto cleanup;

	if (pset.timing)
	{
		INSTR_TIME_SET_CURRENT(after);
		INSTR_TIME_SUBTRACT(after, before);
		*elapsed_msec += INSTR_TIME_GET_MILLISEC(after);
	}

	/*
	 * In \gset mode, we force the fetch count to be 2, so that we will throw
	 * the appropriate error if the query returns more than one row.
	 */
	if (pset.gset_prefix)
		fetch_count = 2;
	else
		fetch_count = pset.fetch_count;

	snprintf(fetch_cmd, sizeof(fetch_cmd),
			 "FETCH FORWARD %d FROM _psql_cursor",
			 fetch_count);

	/* prepare to write output to \g argument, if any */
	if (pset.gfname)
	{
		/* keep this code in sync with PrintQueryTuples */
		pset.queryFout = stdout;	/* so it doesn't get closed */

		/* open file/pipe */
		if (!setQFout(pset.gfname))
		{
			pset.queryFout = queryFout_copy;
			pset.queryFoutPipe = queryFoutPipe_copy;
			OK = false;
			goto cleanup;
		}
	}

	/* clear any pre-existing error indication on the output stream */
	clearerr(pset.queryFout);

	for (;;)
	{
		if (pset.timing)
			INSTR_TIME_SET_CURRENT(before);

		/* get fetch_count tuples at a time */
		results = PQexec(pset.db, fetch_cmd);

		if (pset.timing)
		{
			INSTR_TIME_SET_CURRENT(after);
			INSTR_TIME_SUBTRACT(after, before);
			*elapsed_msec += INSTR_TIME_GET_MILLISEC(after);
		}

		if (PQresultStatus(results) != PGRES_TUPLES_OK)
		{
			/* shut down pager before printing error message */
			if (did_pager)
			{
				ClosePager(pset.queryFout);
				pset.queryFout = queryFout_copy;
				pset.queryFoutPipe = queryFoutPipe_copy;
				did_pager = false;
			}

			OK = AcceptResult(results);
			Assert(!OK);
			PQclear(results);
			break;
		}

		if (pset.gset_prefix)
		{
			/* StoreQueryTuple will complain if not exactly one row */
			OK = StoreQueryTuple(results);
			PQclear(results);
			break;
		}

		ntuples = PQntuples(results);

		if (ntuples < fetch_count)
		{
			/* this is the last result set, so allow footer decoration */
			my_popt.topt.stop_table = true;
		}
		else if (pset.queryFout == stdout && !did_pager)
		{
			/*
			 * If query requires multiple result sets, hack to ensure that
			 * only one pager instance is used for the whole mess
			 */
			pset.queryFout = PageOutput(100000, &(my_popt.topt));
			did_pager = true;
		}

		printQuery(results, &my_popt, pset.queryFout, pset.logfile);

		PQclear(results);

		/* after the first result set, disallow header decoration */
		my_popt.topt.start_table = false;
		my_popt.topt.prior_records += ntuples;

		/*
		 * Make sure to flush the output stream, so intermediate results are
		 * visible to the client immediately.  We check the results because if
		 * the pager dies/exits/etc, there's no sense throwing more data at
		 * it.
		 */
		flush_error = fflush(pset.queryFout);

		/*
		 * Check if we are at the end, if a cancel was pressed, or if there
		 * were any errors either trying to flush out the results, or more
		 * generally on the output stream at all.  If we hit any errors
		 * writing things to the stream, we presume $PAGER has disappeared and
		 * stop bothering to pull down more data.
		 */
		if (ntuples < fetch_count || cancel_pressed || flush_error ||
			ferror(pset.queryFout))
			break;
	}

	/* close \g argument file/pipe, restore old setting */
	if (pset.gfname)
	{
		/* keep this code in sync with PrintQueryTuples */
		setQFout(NULL);

		pset.queryFout = queryFout_copy;
		pset.queryFoutPipe = queryFoutPipe_copy;
	}
	else if (did_pager)
	{
		ClosePager(pset.queryFout);
		pset.queryFout = queryFout_copy;
		pset.queryFoutPipe = queryFoutPipe_copy;
	}

cleanup:
	if (pset.timing)
		INSTR_TIME_SET_CURRENT(before);

	/*
	 * We try to close the cursor on either success or failure, but on failure
	 * ignore the result (it's probably just a bleat about being in an aborted
	 * transaction)
	 */
	results = PQexec(pset.db, "CLOSE _psql_cursor");
	if (OK)
	{
		OK = AcceptResult(results) &&
			(PQresultStatus(results) == PGRES_COMMAND_OK);
	}
	PQclear(results);

	if (started_txn)
	{
		results = PQexec(pset.db, OK ? "COMMIT" : "ROLLBACK");
		OK &= AcceptResult(results) &&
			(PQresultStatus(results) == PGRES_COMMAND_OK);
		PQclear(results);
	}

	if (pset.timing)
	{
		INSTR_TIME_SET_CURRENT(after);
		INSTR_TIME_SUBTRACT(after, before);
		*elapsed_msec += INSTR_TIME_GET_MILLISEC(after);
	}

	return OK;
}
Пример #17
0
/*
 * Generate a new buffer id supposed to be unique for a given layer name
 */
buffer *ows_psql_generate_id(ows * o, buffer * layer_name)
{
    ows_layer_node *ln;
    buffer * id, *sql_id;
    FILE *fp;
    PGresult * res;
    int i, seed_len;
    char * seed = NULL;

    assert(o);
    assert(o->layers);
    assert(layer_name);

    /* Retrieve layer node pointer */
    for (ln = o->layers->first ; ln ; ln = ln->next) {
        if (ln->layer->name && ln->layer->storage
            && !strcmp(ln->layer->name->buf, layer_name->buf)) break;
    }
    assert(ln);

    id = buffer_init();

    /* If PK have a sequence in PostgreSQL database,
     * retrieve next available sequence value
     */
     if (ln->layer->storage->pkey_sequence) {
         sql_id = buffer_init();
         buffer_add_str(sql_id, "SELECT nextval('");
         buffer_copy(sql_id, ln->layer->storage->pkey_sequence);
         buffer_add_str(sql_id, "');");
         res = ows_psql_exec(o, sql_id->buf);
         buffer_free(sql_id);

         if (PQresultStatus(res) == PGRES_TUPLES_OK && PQntuples(res) == 1) {
             buffer_add_str(id, (char *) PQgetvalue(res, 0, 0));
             PQclear(res);
             return id;
         }

         /* FIXME: Shouldn't we return an error there instead ? */
         PQclear(res);
     } 
     
     /*
      * If we don't have a PostgreSQL Sequence, we will try to 
      * generate a pseudo random keystring using /dev/urandom
      * Will so work only on somes/commons Unix system
      */
     seed_len = 6;
     seed = malloc(sizeof(char) * (seed_len * 3 + 1));  /* multiply by 3 to be able to deal
                                                           with hex2dec conversion */ 
     assert(seed);
     seed[0] = '\0';

     fp = fopen("/dev/urandom","r");
     if (fp) {
         for (i=0 ; i<seed_len ; i++)
             sprintf(seed,"%s%03d", seed, fgetc(fp));
         fclose(fp);
         buffer_add_str(id, seed);
         free(seed);

         return id;
     } 
     free(seed);

    /* Case where we not using PostgreSQL sequence, 
     * and OS don't have a /dev/urandom support
     * This case don't prevent to produce ID collision
     * Don't use it unless really no others choices !!!
     */
     srand((int) (time(NULL) ^ rand() % 1000) + 42); 
     srand((rand() % 1000 ^ rand() % 1000) + 42); 
     buffer_add_int(id, rand());

     return id;
}
Пример #18
0
/*
 * PSQLexecWatch
 *
 * This function is used for \watch command to send the query to
 * the server and print out the results.
 *
 * Returns 1 if the query executed successfully, 0 if it cannot be repeated,
 * e.g., because of the interrupt, -1 on error.
 */
int
PSQLexecWatch(const char *query, const printQueryOpt *opt)
{
	PGresult   *res;
	double	elapsed_msec = 0;
	instr_time	before;
	instr_time	after;

	if (!pset.db)
	{
		psql_error("You are currently not connected to a database.\n");
		return 0;
	}

	SetCancelConn();

	if (pset.timing)
		INSTR_TIME_SET_CURRENT(before);

	res = PQexec(pset.db, query);

	ResetCancelConn();

	if (!AcceptResult(res))
	{
		PQclear(res);
		return 0;
	}

	if (pset.timing)
	{
		INSTR_TIME_SET_CURRENT(after);
		INSTR_TIME_SUBTRACT(after, before);
		elapsed_msec = INSTR_TIME_GET_MILLISEC(after);
	}

	/*
	 * If SIGINT is sent while the query is processing, the interrupt
	 * will be consumed.  The user's intention, though, is to cancel
	 * the entire watch process, so detect a sent cancellation request and
	 * exit in this case.
	 */
	if (cancel_pressed)
	{
		PQclear(res);
		return 0;
	}

	switch (PQresultStatus(res))
	{
		case PGRES_TUPLES_OK:
			printQuery(res, opt, pset.queryFout, pset.logfile);
			break;

		case PGRES_COMMAND_OK:
			fprintf(pset.queryFout, "%s\n%s\n\n", opt->title, PQcmdStatus(res));
			break;

		case PGRES_EMPTY_QUERY:
			psql_error(_("\\watch cannot be used with an empty query\n"));
			PQclear(res);
			return -1;

		case PGRES_COPY_OUT:
		case PGRES_COPY_IN:
		case PGRES_COPY_BOTH:
			psql_error(_("\\watch cannot be used with COPY\n"));
			PQclear(res);
			return -1;

		default:
			psql_error(_("unexpected result status for \\watch\n"));
			PQclear(res);
			return -1;
	}

	PQclear(res);

	fflush(pset.queryFout);

	/* Possible microtiming output */
	if (pset.timing)
		printf(_("Time: %.3f ms\n"), elapsed_msec);

	return 1;
}
Пример #19
0
int
main(int argc, char *argv[])
{
	static int	if_exists = 0;

	static struct option long_options[] = {
		{"host", required_argument, NULL, 'h'},
		{"port", required_argument, NULL, 'p'},
		{"username", required_argument, NULL, 'U'},
		{"no-password", no_argument, NULL, 'w'},
		{"password", no_argument, NULL, 'W'},
		{"echo", no_argument, NULL, 'e'},
		{"interactive", no_argument, NULL, 'i'},
		{"if-exists", no_argument, &if_exists, 1},
		{"maintenance-db", required_argument, NULL, 2},
		{NULL, 0, NULL, 0}
	};

	const char *progname;
	int			optindex;
	int			c;

	char	   *dbname = NULL;
	char	   *maintenance_db = NULL;
	char	   *host = NULL;
	char	   *port = NULL;
	char	   *username = NULL;
	enum trivalue prompt_password = TRI_DEFAULT;
	bool		echo = false;
	bool		interactive = false;

	PQExpBufferData sql;

	PGconn	   *conn;
	PGresult   *result;

	progname = get_progname(argv[0]);
	set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pgscripts"));

	handle_help_version_opts(argc, argv, "dropdb", help);

	while ((c = getopt_long(argc, argv, "h:p:U:wWei", long_options, &optindex)) != -1)
	{
		switch (c)
		{
			case 'h':
				host = pg_strdup(optarg);
				break;
			case 'p':
				port = pg_strdup(optarg);
				break;
			case 'U':
				username = pg_strdup(optarg);
				break;
			case 'w':
				prompt_password = TRI_NO;
				break;
			case 'W':
				prompt_password = TRI_YES;
				break;
			case 'e':
				echo = true;
				break;
			case 'i':
				interactive = true;
				break;
			case 0:
				/* this covers the long options */
				break;
			case 2:
				maintenance_db = pg_strdup(optarg);
				break;
			default:
				fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
				exit(1);
		}
	}

	switch (argc - optind)
	{
		case 0:
			fprintf(stderr, _("%s: missing required argument database name\n"), progname);
			fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
			exit(1);
		case 1:
			dbname = argv[optind];
			break;
		default:
			fprintf(stderr, _("%s: too many command-line arguments (first is \"%s\")\n"),
					progname, argv[optind + 1]);
			fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
			exit(1);
	}

	if (interactive)
	{
		printf(_("Database \"%s\" will be permanently removed.\n"), dbname);
		if (!yesno_prompt("Are you sure?"))
			exit(0);
	}

	initPQExpBuffer(&sql);

	appendPQExpBuffer(&sql, "DROP DATABASE %s%s;",
					  (if_exists ? "IF EXISTS " : ""), fmtId(dbname));

	/* Avoid trying to drop postgres db while we are connected to it. */
	if (maintenance_db == NULL && strcmp(dbname, "postgres") == 0)
		maintenance_db = "template1";

	conn = connectMaintenanceDatabase(maintenance_db,
									  host, port, username, prompt_password,
									  progname, echo);

	if (echo)
		printf("%s\n", sql.data);
	result = PQexec(conn, sql.data);
	if (PQresultStatus(result) != PGRES_COMMAND_OK)
	{
		fprintf(stderr, _("%s: database removal failed: %s"),
				progname, PQerrorMessage(conn));
		PQfinish(conn);
		exit(1);
	}

	PQclear(result);
	PQfinish(conn);
	exit(0);
}
Пример #20
0
/*
 * ProcessResult: utility function for use by SendQuery() only
 *
 * When our command string contained a COPY FROM STDIN or COPY TO STDOUT,
 * PQexec() has stopped at the PGresult associated with the first such
 * command.  In that event, we'll marshal data for the COPY and then cycle
 * through any subsequent PGresult objects.
 *
 * When the command string contained no such COPY command, this function
 * degenerates to an AcceptResult() call.
 *
 * Changes its argument to point to the last PGresult of the command string,
 * or NULL if that result was for a COPY TO STDOUT.  (Returning NULL prevents
 * the command status from being printed, which we want in that case so that
 * the status line doesn't get taken as part of the COPY data.)
 *
 * Returns true on complete success, false otherwise.  Possible failure modes
 * include purely client-side problems; check the transaction status for the
 * server-side opinion.
 */
static bool
ProcessResult(PGresult **results)
{
	bool		success = true;
	bool		first_cycle = true;

	for (;;)
	{
		ExecStatusType result_status;
		bool		is_copy;
		PGresult   *next_result;

		if (!AcceptResult(*results))
		{
			/*
			 * Failure at this point is always a server-side failure or a
			 * failure to submit the command string.  Either way, we're
			 * finished with this command string.
			 */
			success = false;
			break;
		}

		result_status = PQresultStatus(*results);
		switch (result_status)
		{
			case PGRES_EMPTY_QUERY:
			case PGRES_COMMAND_OK:
			case PGRES_TUPLES_OK:
				is_copy = false;
				break;

			case PGRES_COPY_OUT:
			case PGRES_COPY_IN:
				is_copy = true;
				break;

			default:
				/* AcceptResult() should have caught anything else. */
				is_copy = false;
				psql_error("unexpected PQresultStatus: %d\n", result_status);
				break;
		}

		if (is_copy)
		{
			/*
			 * Marshal the COPY data.  Either subroutine will get the
			 * connection out of its COPY state, then call PQresultStatus()
			 * once and report any error.
			 *
			 * If pset.copyStream is set, use that as data source/sink,
			 * otherwise use queryFout or cur_cmd_source as appropriate.
			 */
			FILE	   *copystream = pset.copyStream;
			PGresult   *copy_result;

			SetCancelConn();
			if (result_status == PGRES_COPY_OUT)
			{
				if (!copystream)
					copystream = pset.queryFout;
				success = handleCopyOut(pset.db,
										copystream,
										&copy_result) && success;

				/*
				 * Suppress status printing if the report would go to the same
				 * place as the COPY data just went.  Note this doesn't
				 * prevent error reporting, since handleCopyOut did that.
				 */
				if (copystream == pset.queryFout)
				{
					PQclear(copy_result);
					copy_result = NULL;
				}
			}
			else
			{
				if (!copystream)
					copystream = pset.cur_cmd_source;
				success = handleCopyIn(pset.db,
									   copystream,
									   PQbinaryTuples(*results),
									   &copy_result) && success;
			}
			ResetCancelConn();

			/*
			 * Replace the PGRES_COPY_OUT/IN result with COPY command's exit
			 * status, or with NULL if we want to suppress printing anything.
			 */
			PQclear(*results);
			*results = copy_result;
		}
		else if (first_cycle)
		{
			/* fast path: no COPY commands; PQexec visited all results */
			break;
		}

		/*
		 * Check PQgetResult() again.  In the typical case of a single-command
		 * string, it will return NULL.  Otherwise, we'll have other results
		 * to process that may include other COPYs.  We keep the last result.
		 */
		next_result = PQgetResult(pset.db);
		if (!next_result)
			break;

		PQclear(*results);
		*results = next_result;
		first_cycle = false;
	}

	/* may need this to recover from conn loss during COPY */
	if (!first_cycle && !CheckConnection())
		return false;

	return success;
}
Пример #21
0
/*
 * Send a query and wait for the results by using the asynchronous libpq
 * functions and the backend version of select().
 *
 * We must not use the regular blocking libpq functions like PQexec()
 * since they are uninterruptible by signals on some platforms, such as
 * Windows.
 *
 * We must also not use vanilla select() here since it cannot handle the
 * signal emulation layer on Windows.
 *
 * The function is modeled on PQexec() in libpq, but only implements
 * those parts that are in use in the walreceiver.
 *
 * Queries are always executed on the connection in streamConn.
 */
static PGresult *
libpqrcv_PQexec(const char *query)
{
	PGresult   *result		= NULL;
	PGresult   *lastResult	= NULL;

	/*
	 * PQexec() silently discards any prior query results on the
	 * connection. This is not required for walreceiver since it's
	 * expected that walsender won't generate any such junk results.
	 */

	/*
	 * Submit a query. Since we don't use non-blocking mode, this also
	 * can block. But its risk is relatively small, so we ignore that
	 * for now.
	 */
	if (!PQsendQuery(streamConn, query))
		return NULL;

	for (;;)
	{
		/*
		 * Receive data until PQgetResult is ready to get the result
		 * without blocking.
		 */
		while (PQisBusy(streamConn))
		{
			/*
			 * We don't need to break down the sleep into smaller increments,
			 * and check for interrupts after each nap, since we can just
			 * elog(FATAL) within SIGTERM signal handler if the signal
			 * arrives in the middle of establishment of replication connection.
			 */
			if (!libpq_select(-1))
				continue;		/* interrupted */
			if (PQconsumeInput(streamConn) == 0)
				return NULL;	/* trouble */
		}

		/*
		 * Emulate the PQexec()'s behavior of returning the last result
		 * when there are many.
		 * Since walsender will never generate multiple results, we skip
		 * the concatenation of error messages.
		 */
		result = PQgetResult(streamConn);
		if (result == NULL)
			break;				/* query is complete */

		PQclear(lastResult);
		lastResult = result;

		if (PQresultStatus(lastResult) == PGRES_COPY_IN ||
			PQresultStatus(lastResult) == PGRES_COPY_OUT ||
			PQstatus(streamConn) == CONNECTION_BAD)
			break;
	}

	return lastResult;
}
Пример #22
0
/*
 * SendQuery: send the query string to the backend
 * (and print out results)
 *
 * Note: This is the "front door" way to send a query. That is, use it to
 * send queries actually entered by the user. These queries will be subject to
 * single step mode.
 * To send "back door" queries (generated by slash commands, etc.) in a
 * controlled way, use PSQLexec().
 *
 * Returns true if the query executed successfully, false otherwise.
 */
bool
SendQuery(const char *query)
{
	PGresult   *results;
	PGTransactionStatusType transaction_status;
	double		elapsed_msec = 0;
	bool		OK = false;
	bool		on_error_rollback_savepoint = false;
	static bool on_error_rollback_warning = false;

	if (!pset.db)
	{
		psql_error("You are currently not connected to a database.\n");
		goto sendquery_cleanup;
	}

	if (pset.singlestep)
	{
		char		buf[3];

		printf(_("***(Single step mode: verify command)*******************************************\n"
				 "%s\n"
				 "***(press return to proceed or enter x and return to cancel)********************\n"),
			   query);
		fflush(stdout);
		if (fgets(buf, sizeof(buf), stdin) != NULL)
			if (buf[0] == 'x')
				goto sendquery_cleanup;
	}
	else if (pset.echo == PSQL_ECHO_QUERIES)
	{
		puts(query);
		fflush(stdout);
	}

	if (pset.logfile)
	{
		fprintf(pset.logfile,
				_("********* QUERY **********\n"
				  "%s\n"
				  "**************************\n\n"), query);
		fflush(pset.logfile);
	}

	SetCancelConn();

	transaction_status = PQtransactionStatus(pset.db);

	if (transaction_status == PQTRANS_IDLE &&
		!pset.autocommit &&
		!command_no_begin(query))
	{
		results = PQexec(pset.db, "BEGIN");
		if (PQresultStatus(results) != PGRES_COMMAND_OK)
		{
			psql_error("%s", PQerrorMessage(pset.db));
			PQclear(results);
			ResetCancelConn();
			goto sendquery_cleanup;
		}
		PQclear(results);
		transaction_status = PQtransactionStatus(pset.db);
	}

	if (transaction_status == PQTRANS_INTRANS &&
		pset.on_error_rollback != PSQL_ERROR_ROLLBACK_OFF &&
		(pset.cur_cmd_interactive ||
		 pset.on_error_rollback == PSQL_ERROR_ROLLBACK_ON))
	{
		if (on_error_rollback_warning == false && pset.sversion < 80000)
		{
			psql_error("The server (version %d.%d) does not support savepoints for ON_ERROR_ROLLBACK.\n",
					   pset.sversion / 10000, (pset.sversion / 100) % 100);
			on_error_rollback_warning = true;
		}
		else
		{
			results = PQexec(pset.db, "SAVEPOINT pg_psql_temporary_savepoint");
			if (PQresultStatus(results) != PGRES_COMMAND_OK)
			{
				psql_error("%s", PQerrorMessage(pset.db));
				PQclear(results);
				ResetCancelConn();
				goto sendquery_cleanup;
			}
			PQclear(results);
			on_error_rollback_savepoint = true;
		}
	}

	if (pset.fetch_count <= 0 || !is_select_command(query))
	{
		/* Default fetch-it-all-and-print mode */
		instr_time	before,
					after;

		if (pset.timing)
			INSTR_TIME_SET_CURRENT(before);

		results = PQexec(pset.db, query);

		/* these operations are included in the timing result: */
		ResetCancelConn();
		OK = ProcessResult(&results);

		if (pset.timing)
		{
			INSTR_TIME_SET_CURRENT(after);
			INSTR_TIME_SUBTRACT(after, before);
			elapsed_msec = INSTR_TIME_GET_MILLISEC(after);
		}

		/* but printing results isn't: */
		if (OK && results)
			OK = PrintQueryResults(results);
	}
	else
	{
		/* Fetch-in-segments mode */
		OK = ExecQueryUsingCursor(query, &elapsed_msec);
		ResetCancelConn();
		results = NULL;			/* PQclear(NULL) does nothing */
	}

	if (!OK && pset.echo == PSQL_ECHO_ERRORS)
		psql_error("STATEMENT:  %s\n", query);

	/* If we made a temporary savepoint, possibly release/rollback */
	if (on_error_rollback_savepoint)
	{
		const char *svptcmd = NULL;

		transaction_status = PQtransactionStatus(pset.db);

		switch (transaction_status)
		{
			case PQTRANS_INERROR:
				/* We always rollback on an error */
				svptcmd = "ROLLBACK TO pg_psql_temporary_savepoint";
				break;

			case PQTRANS_IDLE:
				/* If they are no longer in a transaction, then do nothing */
				break;

			case PQTRANS_INTRANS:

				/*
				 * Do nothing if they are messing with savepoints themselves:
				 * If the user did RELEASE or ROLLBACK, our savepoint is gone.
				 * If they issued a SAVEPOINT, releasing ours would remove
				 * theirs.
				 */
				if (results &&
					(strcmp(PQcmdStatus(results), "SAVEPOINT") == 0 ||
					 strcmp(PQcmdStatus(results), "RELEASE") == 0 ||
					 strcmp(PQcmdStatus(results), "ROLLBACK") == 0))
					svptcmd = NULL;
				else
					svptcmd = "RELEASE pg_psql_temporary_savepoint";
				break;

			case PQTRANS_ACTIVE:
			case PQTRANS_UNKNOWN:
			default:
				OK = false;
				/* PQTRANS_UNKNOWN is expected given a broken connection. */
				if (transaction_status != PQTRANS_UNKNOWN || ConnectionUp())
					psql_error("unexpected transaction status (%d)\n",
							   transaction_status);
				break;
		}

		if (svptcmd)
		{
			PGresult   *svptres;

			svptres = PQexec(pset.db, svptcmd);
			if (PQresultStatus(svptres) != PGRES_COMMAND_OK)
			{
				psql_error("%s", PQerrorMessage(pset.db));
				PQclear(svptres);
				OK = false;

				PQclear(results);
				ResetCancelConn();
				goto sendquery_cleanup;
			}
			PQclear(svptres);
		}
	}

	PQclear(results);

	/* Possible microtiming output */
	if (pset.timing)
		printf(_("Time: %.3f ms\n"), elapsed_msec);

	/* check for events that may occur during query execution */

	if (pset.encoding != PQclientEncoding(pset.db) &&
		PQclientEncoding(pset.db) >= 0)
	{
		/* track effects of SET CLIENT_ENCODING */
		pset.encoding = PQclientEncoding(pset.db);
		pset.popt.topt.encoding = pset.encoding;
		SetVariable(pset.vars, "ENCODING",
					pg_encoding_to_char(pset.encoding));
	}

	PrintNotifications();

	/* perform cleanup that should occur after any attempted query */

sendquery_cleanup:

	/* reset \g's output-to-filename trigger */
	if (pset.gfname)
	{
		free(pset.gfname);
		pset.gfname = NULL;
	}

	/* reset \gset trigger */
	if (pset.gset_prefix)
	{
		free(pset.gset_prefix);
		pset.gset_prefix = NULL;
	}

	return OK;
}
Пример #23
0
int
main(int argc, char **argv)
{
    const char *conninfo;
    PGconn     *conn;
    PGresult   *res;
    int         nFields;
    int         i,
                j;

    if (argc > 1)
        conninfo = argv[1];
    else
        conninfo = "host=localhost port=5432 user=korisk dbname=test";

    /* Make a connection to the database */
    conn = PQconnectdb(conninfo);

    /* Check to see that the backend connection was successfully made */
    if (PQstatus(conn) != CONNECTION_OK)
    {
        fprintf(stderr, "Connection to database failed: %s",
                PQerrorMessage(conn));
        exit_nicely(conn);
    }

    /* Start a transaction block */
    res = PQexec(conn, "BEGIN");
    if (PQresultStatus(res) != PGRES_COMMAND_OK)
    {
        fprintf(stderr, "BEGIN command failed: %s", PQerrorMessage(conn));
        PQclear(res);
        exit_nicely(conn);
    }
    PQclear(res);

       /*
 *      * Should PQclear PGresult whenever it is no longer needed to avoid memory
 *      * leaks
 *      */
	
    res = PQprepare(conn, "qu", "insert into mrow values ($1::bigint, $2::bigint, $3::float);",3, NULL);
    if (PQresultStatus(res) != PGRES_COMMAND_OK)
    {
        fprintf(stderr, "Prepare query failed: %s", PQerrorMessage(conn));
        PQclear(res);
        exit_nicely(conn);
    }
    PQclear(res);
	
   const char *paramValues[3];
   int         paramLengths[3];
   int         paramFormats[3];	


   long time = 0, _time = 0;
   long id = 0, _id = 0;
  
   union{
	double  f;
	long     i;
   } _value, value;

   _value.f = 1.0;
    value.f = 1.0;
   
   paramValues[0] = (char*)(&time);
   paramLengths[0] = sizeof(time);
   paramFormats[0] = 1;

   paramValues[1] = (char*)(&id);
   paramLengths[1] = sizeof(id);
   paramFormats[1] = 1;
   
   paramValues[2] = (char*)(&value);
   paramLengths[2] = sizeof(value);
   paramFormats[2] = 1;

   for(i=0; i < 3; i++){
   	time = htobe64(_time);
   	id = htobe64(_id);
 	value.i = htobe64(_value.i);

	_time++;
   	_id++;
   	_value.f += 0.1;

	res = PQexecPrepared(conn, "qu", 3, paramValues, paramLengths, paramFormats, 1);
	if (PQresultStatus(res) != PGRES_COMMAND_OK){
		fprintf(stderr, "Exec Prepared query failed: %s", PQerrorMessage(conn));
        	PQclear(res);
	        exit_nicely(conn);
	}
    	PQclear(res);
   }




 /*
     end the transaction */
    res = PQexec(conn, "END");
    PQclear(res);

    /* close the connection to the database and cleanup */
    PQfinish(conn);

    return 0;
}
Пример #24
0
double CPokerTrackerThread::UpdateStat(int m_chr, int stat)
{
	PGresult	*res = NULL;
	char		strQry[k_max_length_of_query] = {0};
	char		strQry1[k_max_length_of_query] = {0};
	char		strQry2[k_max_length_of_query] = {0};
	const char	*n = NULL;
	double		result = -1.0;
	char		siteidstr[k_max_length_of_site_id] = {0};
	int			siteid = 0;
	clock_t		updStart, updEnd;
	int			duration;

	int sym_elapsed = p_symbol_engine_time->elapsed();

	//No more unnecessary queries when we don't even have a siteid to check
	siteid = pt_lookup.GetSiteId();
	if (siteid == k_undefined)
		return result;

	if (!_connected || PQstatus(_pgconn) != CONNECTION_OK)
		return result;

	assert(m_chr >= k_min_chair_number);
	assert(m_chr <= k_max_chair_number);
	assert(stat >= pt_min);
	assert(stat <= pt_max);

	/* TS 01/25/2011.  Update means update... we will not back off now :-) */
	
	// If we already have stats cached for the player, the timeout has not expired,
	// return the value from the cache...
	//if (sym_elapsed - _player_stats[m_chr].t_elapsed[stat] < prefs.pt_cache_refresh() &&
		//_player_stats[m_chr].t_elapsed[stat] != -1 &&
		//_player_stats[m_chr].stat[stat] != -1)
	//{
		//result = _player_stats[m_chr].stat[stat];
	//}

	// ...otherwise query the database
	//else
	{
		// get query string for the requested statistic
		strcpy_s(strQry, k_max_length_of_query, query_str3[stat]);

		// Insert the player name in the query string
		strcpy_s(strQry1, k_max_length_of_query, strQry);  // move the query into temp str 1
		while ((n=strstr(strQry1, "%SCREENNAME%"))!=NULL) // find the token in temp str 1
		{
			strcpy_s(strQry2, k_max_length_of_query, strQry1);  // move the query into temp str 2
			strQry2[n-strQry1]='\0';  // cut off temp str 2 at the beginning of the token
			strcat_s(strQry2, k_max_length_of_query, _player_stats[m_chr].pt_name);  // append the player name to temp str 2
			strcat_s(strQry2, k_max_length_of_query, n+12); // append the portion of temp str 1 after the token to temp str 2
			strcpy_s(strQry, k_max_length_of_query, strQry2); // move temp str 2 into the original query
			strcpy_s(strQry1, k_max_length_of_query, strQry);  // move the query into temp str 1
		}

		// Insert the site id in the query string
		sprintf_s(siteidstr, k_max_length_of_site_id, "%d", siteid);
		strcpy_s(strQry1, k_max_length_of_query, strQry);  // move the query into temp str 1
		while ((n=strstr(strQry1, "%SITEID%"))!=NULL)   // find the token in temp str 1
		{
			strcpy_s(strQry2, k_max_length_of_query, strQry1);  // move the query into temp str 2
			strQry2[n-strQry1]='\0';  // cut off temp str 2 at the beginning of the token
			strcat_s(strQry2, k_max_length_of_query, siteidstr);  // append the site id to temp str 2
			strcat_s(strQry2, k_max_length_of_query, n+8); // append the portion of temp str 1 after the token to temp str 2
			strcpy_s(strQry, k_max_length_of_query, strQry2); // move temp str 2 into the original query
			strcpy_s(strQry1, k_max_length_of_query, strQry);  // move the query into temp str 1
		}

		// Do the query against the PT database
		updStart = clock();
		try
		{
			// See if we can find the player name in the database
			write_log_pokertracker(prefs.debug_pokertracker(), "Querying %s for m_chr %d: %s\n", stat_str[stat], m_chr, strQry);
			res = PQexec(_pgconn, strQry);
		}
		catch (_com_error &e)
		{
			write_log_pokertracker(prefs.debug_pokertracker(), "ERROR\n");
			write_log_pokertracker(prefs.debug_pokertracker(), _T("\tCode = %08lx\n"), e.Error());
			write_log_pokertracker(prefs.debug_pokertracker(), _T("\tCode meaning = %s\n"), e.ErrorMessage());
			_bstr_t bstrSource(e.Source());
			_bstr_t bstrDescription(e.Description());
			write_log_pokertracker(prefs.debug_pokertracker(), _T("\tSource = %s\n"), (LPCTSTR) bstrSource);
			write_log_pokertracker(prefs.debug_pokertracker(), _T("\tDescription = %s\n"), (LPCTSTR) bstrDescription);
			write_log_pokertracker(prefs.debug_pokertracker(), _T("\tQuery = [%s]\n"), strQry);
		}
		
		updEnd = clock();
		duration = (int) ((double)(updEnd - updStart) / 1000);
		if (duration >= 3)
			write_log_pokertracker(2, "Query time in seconds: [%d]\n", duration);

		// Check query return code
		if (PQresultStatus(res) != PGRES_TUPLES_OK)
		{
			switch (PQresultStatus(res))
			{
			case PGRES_COMMAND_OK:
				write_log_pokertracker(prefs.debug_pokertracker(), "PGRES_COMMAND_OK: %s [%s]\n", PQerrorMessage(_pgconn), strQry);
				break;
			case PGRES_EMPTY_QUERY:
				write_log_pokertracker(prefs.debug_pokertracker(), "PGRES_EMPTY_QUERY: %s [%s]\n", PQerrorMessage(_pgconn), strQry);
				break;
			case PGRES_BAD_RESPONSE:
				write_log_pokertracker(prefs.debug_pokertracker(), "PGRES_BAD_RESPONSE: %s [%s]\n", PQerrorMessage(_pgconn), strQry);
				break;
			case PGRES_COPY_OUT:
				write_log_pokertracker(prefs.debug_pokertracker(), "PGRES_COPY_OUT: %s [%s]\n", PQerrorMessage(_pgconn), strQry);
				break;
			case PGRES_COPY_IN:
				write_log_pokertracker(prefs.debug_pokertracker(), "PGRES_COPY_IN: %s [%s]\n", PQerrorMessage(_pgconn), strQry);
				break;
			case PGRES_NONFATAL_ERROR:
				write_log_pokertracker(prefs.debug_pokertracker(), "PGRES_NONFATAL_ERROR: %s [%s]\n", PQerrorMessage(_pgconn), strQry);
				break;
			case PGRES_FATAL_ERROR:
				write_log_pokertracker(prefs.debug_pokertracker(), "PGRES_FATAL_ERROR: %s [%s]\n", PQerrorMessage(_pgconn), strQry);
				break;
			default:
				write_log_pokertracker(prefs.debug_pokertracker(), "GENERIC ERROR: %s [%s]\n", PQerrorMessage(_pgconn), strQry);
				break;
			}
		}
		else
		{
			if (PQgetisnull(res,0,0) != 1)
			{
				result = atof(PQgetvalue(res,0,0));
				write_log_pokertracker(prefs.debug_pokertracker(), "Query %s for m_chr %d success: %f\n", stat_str[stat], m_chr, result);
			}
		}

		PQclear(res);

		// update cache with new values
		_player_stats[m_chr].stat[stat] = result;
		_player_stats[m_chr].t_elapsed[stat] = sym_elapsed;
	}

	return result;
}
Пример #25
0
int
main(int argc, char **argv)
{
	const char *conninfo;
	TestSpec   *testspec;
	int			i;

	/*
	 * If the user supplies a parameter on the command line, use it as the
	 * conninfo string; otherwise default to setting dbname=postgres and
	 * using environment variables or defaults for all other connection
	 * parameters.
	 */
	if (argc > 1)
		conninfo = argv[1];
	else
		conninfo = "dbname = postgres";

	/* Read the test spec from stdin */
	spec_yyparse();
	testspec = &parseresult;
	printf("Parsed test spec with %d sessions\n", testspec->nsessions);

	/* Establish connections to the database, one for each session */
	nconns = testspec->nsessions;
	conns = calloc(nconns, sizeof(PGconn *));
	for (i = 0; i < testspec->nsessions; i++)
	{
		PGresult *res;

		conns[i] = PQconnectdb(conninfo);
		if (PQstatus(conns[i]) != CONNECTION_OK)
		{
			fprintf(stderr, "Connection %d to database failed: %s",
					i, PQerrorMessage(conns[i]));
			exit_nicely();
		}

		/*
		 * Suppress NOTIFY messages, which otherwise pop into results at odd
		 * places.
		 */
		res = PQexec(conns[i], "SET client_min_messages = warning;");
		if (PQresultStatus(res) != PGRES_COMMAND_OK)
		{
			fprintf(stderr, "message level setup failed: %s", PQerrorMessage(conns[i]));
			exit_nicely();
		}
		PQclear(res);
	}

	/* Set the session index fields in steps. */
	for (i = 0; i < testspec->nsessions; i++)
	{
		Session *session = testspec->sessions[i];
		int		stepindex;
		for (stepindex = 0; stepindex < session->nsteps; stepindex++)
			session->steps[stepindex]->session = i;
	}

	/*
	 * Run the permutations specified in the spec, or all if none were
	 * explicitly specified.
	 */
	if (testspec->permutations)
		run_named_permutations(testspec);
	else
		run_all_permutations(testspec);

	/* Clean up and exit */
	for (i = 0; i < nconns; i++)
		PQfinish(conns[i]);
	return 0;
}
Пример #26
0
bool QgsShapeFile::insertLayer( QString dbname, QString schema, QString primary_key, QString geom_col,
                                QString srid, PGconn * conn, QProgressDialog& pro, bool &fin,
                                QString& errorText )
{
  Q_UNUSED( dbname );
  connect( &pro, SIGNAL( canceled() ), this, SLOT( cancelImport() ) );
  import_canceled = false;
  bool result = true;

  QString query = QString( "CREATE TABLE %1.%2(%3 SERIAL PRIMARY KEY" )
                  .arg( QgsPgUtil::quotedIdentifier( schema ) )
                  .arg( QgsPgUtil::quotedIdentifier( table_name ) )
                  .arg( QgsPgUtil::quotedIdentifier( primary_key ) );

  for ( uint n = 0; n < column_names.size() && result; n++ )
  {
    query += QString( ",%1 %2" )
             .arg( QgsPgUtil::quotedIdentifier( column_names[n] ) )
             .arg( column_types[n] );
  }
  query += " )";

  QgsDebugMsg( "Query string is: " + query );

  PGresult *res = PQexec( conn, query.toUtf8() );

  if ( PQresultStatus( res ) != PGRES_COMMAND_OK )
  {
    // flag error and send query and error message to stdout on debug
    errorText += tr( "The database gave an error while executing this SQL:\n%1\nThe error was:\n%2\n" )
                 .arg( query ).arg( PQresultErrorMessage( res ) );
    PQclear( res );
    return false;
  }
  else
  {
    PQclear( res );
  }

  query = QString( "SELECT AddGeometryColumn(%1,%2,%3,%4,%5,2)" )
          .arg( QgsPgUtil::quotedValue( schema ) )
          .arg( QgsPgUtil::quotedValue( table_name ) )
          .arg( QgsPgUtil::quotedValue( geom_col ) )
          .arg( srid )
          .arg( QgsPgUtil::quotedValue( geom_type ) );

  res = PQexec( conn, query.toUtf8() );

  if ( PQresultStatus( res ) != PGRES_TUPLES_OK )
  {
    errorText += tr( "The database gave an error while executing this SQL:\n%1\nThe error was:\n%2\n" )
                 .arg( query ).arg( PQresultErrorMessage( res ) );
    PQclear( res );
    return false;
  }
  else
  {
    PQclear( res );
  }

  if ( isMulti )
  {
    query = QString( "select constraint_name from information_schema.table_constraints where table_schema=%1 and table_name=%2 and constraint_name in ('$2','enforce_geotype_the_geom')" )
            .arg( QgsPgUtil::quotedValue( schema ) )
            .arg( QgsPgUtil::quotedValue( table_name ) );

    QStringList constraints;
    res = PQexec( conn, query.toUtf8() );
    if ( PQresultStatus( res ) == PGRES_TUPLES_OK )
    {
      for ( int i = 0; i < PQntuples( res ); i++ )
        constraints.append( PQgetvalue( res, i, 0 ) );
    }
    PQclear( res );

    if ( constraints.size() > 0 )
    {
      // drop the check constraint
      // TODO This whole concept needs to be changed to either
      // convert the geometries to the same type or allow
      // multiple types in the check constraint. For now, we
      // just drop the constraint...
      query = QString( "alter table %1 drop constraint %2" )
              .arg( QgsPgUtil::quotedIdentifier( table_name ) )
              .arg( QgsPgUtil::quotedIdentifier( constraints[0] ) );

      res = PQexec( conn, query.toUtf8() );
      if ( PQresultStatus( res ) != PGRES_COMMAND_OK )
      {
        errorText += tr( "The database gave an error while executing this SQL:\n%1\nThe error was:\n%2\n" )
                     .arg( query ).arg( PQresultErrorMessage( res ) );
        PQclear( res );
        return false;
      }

      PQclear( res );
    }

  }

  //adding the data into the table
  for ( int m = 0; m < features && result; m++ )
  {
    if ( import_canceled )
    {
      fin = true;
      break;
    }

    OGRFeatureH feat = OGR_L_GetNextFeature( ogrLayer );
    if ( feat )
    {
      OGRGeometryH geom = OGR_F_GetGeometryRef( feat );
      if ( geom )
      {
        query = QString( "INSERT INTO %1.%2(" )
                .arg( QgsPgUtil::quotedIdentifier( schema ) )
                .arg( QgsPgUtil::quotedIdentifier( table_name ) );
        QString values = " VALUES (";

        char *geo_temp;
        // 'GeometryFromText' supports only 2D coordinates
        // TODO for proper 2.5D support we would need to use 'GeomFromEWkt'
        if ( hasMoreDimensions )
          OGR_G_SetCoordinateDimension( geom, 2 );
        OGR_G_ExportToWkt( geom, &geo_temp );
        QString geometry( geo_temp );
        CPLFree( geo_temp );

        for ( uint n = 0; n < column_types.size(); n++ )
        {
          QString val;

          // FIXME: OGR_F_GetFieldAsString returns junk when called with a 8.255 float field
          if ( column_types[n] == "float" )
            val = qgsDoubleToString( OGR_F_GetFieldAsDouble( feat, n ) );
          else
            val = codec->toUnicode( OGR_F_GetFieldAsString( feat, n ) );

          if ( val.isEmpty() )
            val = "NULL";
          else
            val = QgsPgUtil::quotedValue( val );

          if ( n > 0 )
          {
            query += ",";
            values += ",";
          }
          query += QgsPgUtil::quotedIdentifier( column_names[n] );
          values += val;
        }
        query += "," + QgsPgUtil::quotedIdentifier( geom_col );
        values += QString( ",st_geometryfromtext(%1,%2)" )
                  .arg( QgsPgUtil::quotedValue( geometry ) )
                  .arg( srid );

        query += ")" + values + ")";

        if ( result )
          res = PQexec( conn, query.toUtf8() );

        if ( PQresultStatus( res ) != PGRES_COMMAND_OK )
        {
          // flag error and send query and error message to stdout on debug
          result = false;
          errorText += tr( "The database gave an error while executing this SQL:" ) + "\n";
          // the query string can be quite long. Trim if necessary...
          if ( query.count() > 100 )
            errorText += query.left( 150 ) +
                         tr( "... (rest of SQL trimmed)", "is appended to a truncated SQL statement" ) +
                         "\n";
          else
            errorText += query + '\n';
          errorText += tr( "The error was:\n%1\n" ).arg( PQresultErrorMessage( res ) );
          errorText += '\n';
        }
        else
        {
          PQclear( res );
        }

        pro.setValue( pro.value() + 1 );
        qApp->processEvents();
      }
      OGR_F_Destroy( feat );
    }
  }
  // create the GIST index if the load was successful
  if ( result )
  {
    // prompt user to see if they want to build the index and warn
    // them about the potential time-cost
  }
  OGR_L_ResetReading( ogrLayer );
  return result;
}
Пример #27
0
/*
 * Actual code to make call to the database and print the output data.
 */
int
sql_exec(PGconn *conn, const char *todo, bool quiet)
{
	PGresult   *res;

	int			nfields;
	int			nrows;
	int			i,
				j,
				l;
	int		   *length;
	char	   *pad;

	/* make the call */
	res = PQexec(conn, todo);

	/* check and deal with errors */
	if (!res || PQresultStatus(res) > 2)
	{
		fprintf(stderr, "oid2name: query failed: %s\n", PQerrorMessage(conn));
		fprintf(stderr, "oid2name: query was: %s\n", todo);

		PQclear(res);
		PQfinish(conn);
		exit(-1);
	}

	/* get the number of fields */
	nrows = PQntuples(res);
	nfields = PQnfields(res);

	/* for each field, get the needed width */
	length = (int *) pg_malloc(sizeof(int) * nfields);
	for (j = 0; j < nfields; j++)
		length[j] = strlen(PQfname(res, j));

	for (i = 0; i < nrows; i++)
	{
		for (j = 0; j < nfields; j++)
		{
			l = strlen(PQgetvalue(res, i, j));
			if (l > length[j])
				length[j] = strlen(PQgetvalue(res, i, j));
		}
	}

	/* print a header */
	if (!quiet)
	{
		for (j = 0, l = 0; j < nfields; j++)
		{
			fprintf(stdout, "%*s", length[j] + 2, PQfname(res, j));
			l += length[j] + 2;
		}
		fprintf(stdout, "\n");
		pad = (char *) pg_malloc(l + 1);
		MemSet(pad, '-', l);
		pad[l] = '\0';
		fprintf(stdout, "%s\n", pad);
		free(pad);
	}

	/* for each row, dump the information */
	for (i = 0; i < nrows; i++)
	{
		for (j = 0; j < nfields; j++)
			fprintf(stdout, "%*s", length[j] + 2, PQgetvalue(res, i, j));
		fprintf(stdout, "\n");
	}

	/* cleanup */
	PQclear(res);
	free(length);

	return 0;
}
Пример #28
0
/*
 * call-seq:
 *    res.result_status() -> Fixnum
 *
 * Returns the status of the query. The status value is one of:
 * * +PGRES_EMPTY_QUERY+
 * * +PGRES_COMMAND_OK+
 * * +PGRES_TUPLES_OK+
 * * +PGRES_COPY_OUT+
 * * +PGRES_COPY_IN+
 * * +PGRES_BAD_RESPONSE+
 * * +PGRES_NONFATAL_ERROR+
 * * +PGRES_FATAL_ERROR+
 * * +PGRES_COPY_BOTH+
 */
static VALUE
pgresult_result_status(VALUE self)
{
	return INT2FIX(PQresultStatus(pgresult_get(self)));
}
Пример #29
0
/*
 * handleCopyOut
 * receives data as a result of a COPY ... TO STDOUT command
 *
 * conn should be a database connection that you just issued COPY TO on
 * and got back a PGRES_COPY_OUT result.
 * copystream is the file stream for the data to go to.
 *
 * result is true if successful, false if not.
 */
bool
handleCopyOut(PGconn *conn, FILE *copystream)
{
	bool		OK = true;
	char	   *buf;
	int			ret;
	PGresult   *res;

	for (;;)
	{
		ret = PQgetCopyData(conn, &buf, 0);

		if (ret < 0)
			break;				/* done or error */

		if (buf)
		{
			if (fwrite(buf, 1, ret, copystream) != ret)
			{
				if (OK)			/* complain only once, keep reading data */
					psql_error("could not write COPY data: %s\n",
							   strerror(errno));
				OK = false;
			}
			PQfreemem(buf);
		}
	}

	if (OK && fflush(copystream))
	{
		psql_error("could not write COPY data: %s\n",
				   strerror(errno));
		OK = false;
	}

	if (ret == -2)
	{
		psql_error("COPY data transfer failed: %s", PQerrorMessage(conn));
		OK = false;
	}

	/*
	 * Check command status and return to normal libpq state.  After a
	 * client-side error, the server will remain ready to deliver data.  The
	 * cleanest thing is to fully drain and discard that data.	If the
	 * client-side error happened early in a large file, this takes a long
	 * time.  Instead, take advantage of the fact that PQexec() will silently
	 * end any ongoing PGRES_COPY_OUT state.  This does cause us to lose the
	 * results of any commands following the COPY in a single command string.
	 * It also only works for protocol version 3.  XXX should we clean up
	 * using the slow way when the connection is using protocol version 2?
	 *
	 * We must not ever return with the status still PGRES_COPY_OUT.  Our
	 * caller is unable to distinguish that situation from reaching the next
	 * COPY in a command string that happened to contain two consecutive COPY
	 * TO STDOUT commands.	We trust that no condition can make PQexec() fail
	 * indefinitely while retaining status PGRES_COPY_OUT.
	 */
	while (res = PQgetResult(conn), PQresultStatus(res) == PGRES_COPY_OUT)
	{
		OK = false;
		PQclear(res);

		PQexec(conn, "-- clear PGRES_COPY_OUT state");
	}
	if (PQresultStatus(res) != PGRES_COMMAND_OK)
	{
		psql_error("%s", PQerrorMessage(conn));
		OK = false;
	}
	PQclear(res);

	return OK;
}
/* Advance to the next state during an async connection setup
 *
 * If the connection is green, this is performed by the regular
 * sync code so the queries are sent by conn_setup() while in
 * CONN_STATUS_READY state.
 */
static int
_conn_poll_setup_async(connectionObject *self)
{
    int res = PSYCO_POLL_ERROR;
    PGresult *pgres;

    switch (self->status) {
    case CONN_STATUS_CONNECTING:
        /* Set the connection to nonblocking now. */
        if (pq_set_non_blocking(self, 1) != 0) {
            break;
        }

        self->equote = conn_get_standard_conforming_strings(self->pgconn);
        self->protocol = conn_get_protocol_version(self->pgconn);
        self->server_version = conn_get_server_version(self->pgconn);
        if (3 != self->protocol) {
            PyErr_SetString(InterfaceError, "only protocol 3 supported");
            break;
        }
        if (0 > conn_read_encoding(self, self->pgconn)) {
            break;
        }
        self->cancel = conn_get_cancel(self->pgconn);
        if (self->cancel == NULL) {
            PyErr_SetString(OperationalError, "can't get cancellation key");
            break;
        }

        /* asynchronous connections always use isolation level 0, the user is
         * expected to manage the transactions himself, by sending
         * (asynchronously) BEGIN and COMMIT statements.
         */
        self->autocommit = 1;

        /* If the datestyle is ISO or anything else good,
         * we can skip the CONN_STATUS_DATESTYLE step. */
        if (!conn_is_datestyle_ok(self->pgconn)) {
            Dprintf("conn_poll: status -> CONN_STATUS_DATESTYLE");
            self->status = CONN_STATUS_DATESTYLE;
            if (0 == pq_send_query(self, psyco_datestyle)) {
                PyErr_SetString(OperationalError, PQerrorMessage(self->pgconn));
                break;
            }
            Dprintf("conn_poll: async_status -> ASYNC_WRITE");
            self->async_status = ASYNC_WRITE;
            res = PSYCO_POLL_WRITE;
        }
        else {
            Dprintf("conn_poll: status -> CONN_STATUS_READY");
            self->status = CONN_STATUS_READY;
            res = PSYCO_POLL_OK;
        }
        break;

    case CONN_STATUS_DATESTYLE:
        res = _conn_poll_query(self);
        if (res == PSYCO_POLL_OK) {
            res = PSYCO_POLL_ERROR;
            pgres = pq_get_last_result(self);
            if (pgres == NULL || PQresultStatus(pgres) != PGRES_COMMAND_OK ) {
                PyErr_SetString(OperationalError, "can't set datestyle to ISO");
                break;
            }
            CLEARPGRES(pgres);

            Dprintf("conn_poll: status -> CONN_STATUS_READY");
            self->status = CONN_STATUS_READY;
            res = PSYCO_POLL_OK;
        }
        break;
    }
    return res;
}