/*
* 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;
TimevalStruct before,
after;
bool OK;
if (!pset.db)
{
psql_error("You are currently not connected to a database.\n");
return false;
}
if (GetVariableBool(pset.vars, "SINGLESTEP"))
{
char buf[3];
printf(gettext("***(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')
return false;
}
else if (VariableEquals(pset.vars, "ECHO", "queries"))
{
puts(query);
fflush(stdout);
}
SetCancelConn();
if (PQtransactionStatus(pset.db) == PQTRANS_IDLE &&
!GetVariableBool(pset.vars, "AUTOCOMMIT") &&
!is_transact_command(query))
{
results = PQexec(pset.db, "BEGIN");
if (PQresultStatus(results) != PGRES_COMMAND_OK)
{
psql_error("%s", PQerrorMessage(pset.db));
PQclear(results);
ResetCancelConn();
return false;
}
PQclear(results);
}
if (pset.timing)
GETTIMEOFDAY(&before);
results = PQexec(pset.db, query);
/* these operations are included in the timing result: */
OK = (AcceptResult(results) && ProcessCopyResult(results));
if (pset.timing)
GETTIMEOFDAY(&after);
/* but printing results isn't: */
if (OK)
OK = PrintQueryResults(results);
PQclear(results);
/* Possible microtiming output */
if (OK && pset.timing)
printf(gettext("Time: %.3f ms\n"), DIFF_MSEC(&after, &before));
/* 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();
return OK;
}
/*************************************************************************
*
* Function: sql_query
*
* Purpose: Issue a query to the database
*
*************************************************************************/
static int sql_query(SQLSOCK * sqlsocket, SQL_CONFIG *config, char *querystr) {
rlm_sql_postgres_sock *pg_sock = sqlsocket->conn;
int numfields = 0;
char *errorcode;
char *errormsg;
if (config->sqltrace)
radlog(L_DBG,"rlm_sql_postgresql: query:\n%s", querystr);
if (pg_sock->conn == NULL) {
radlog(L_ERR, "rlm_sql_postgresql: Socket not connected");
return SQL_DOWN;
}
pg_sock->result = PQexec(pg_sock->conn, querystr);
/*
* 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 (!pg_sock->result)
{
radlog(L_ERR, "rlm_sql_postgresql: PostgreSQL Query failed Error: %s",
PQerrorMessage(pg_sock->conn));
/* 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 SQL_DOWN;
} else {
ExecStatusType status = PQresultStatus(pg_sock->result);
radlog(L_DBG, "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...
*/
pg_sock->affected_rows = affected_rows(pg_sock->result);
radlog(L_DBG, "rlm_sql_postgresql: query affected rows = %i", pg_sock->affected_rows);
return 0;
break;
case PGRES_TUPLES_OK:
/*Successful completion of a command returning data (such as a SELECT or SHOW).*/
pg_sock->cur_row = 0;
pg_sock->affected_rows = PQntuples(pg_sock->result);
numfields = PQnfields(pg_sock->result); /*Check row storing functions..*/
radlog(L_DBG, "rlm_sql_postgresql: query affected rows = %i , fields = %i", pg_sock->affected_rows, numfields);
return 0;
break;
case PGRES_BAD_RESPONSE:
/*The server's response was not understood.*/
radlog(L_DBG, "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(pg_sock->result, PG_DIAG_SQLSTATE);
errormsg = PQresultErrorField(pg_sock->result, PG_DIAG_MESSAGE_PRIMARY);
radlog(L_DBG, "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 */
//.........这里部分代码省略.........
static int begin_transaction(db_con_t * _h, char *_s)
{
PGresult *mr;
int rv;
/*
** Note:
** The upper layers of code may attempt a transaction
** before opening or having a valid connection to the
** database. We try to sense this, and open the database
** if we have the sqlurl in the _h structure. Otherwise,
** all we can do is return an error.
*/
if(_h)
{
if(CON_CONNECTED(_h))
{
mr = PQexec(CON_CONNECTION(_h), "BEGIN");
if(!mr || PQresultStatus(mr) != PGRES_COMMAND_OK)
{
/*
** We get here if the connection to the
** db is corrupt, which can happen a few
** different ways, but all of them are
** related to the parent process forking,
** or being forked.
*/
PLOG("begin_transaction","corrupt connection");
CON_CONNECTED(_h) = 0;
}
else
{
/*
** this is the normal way out.
** the transaction ran fine.
*/
PQclear(mr);
return(0);
}
}
else
{
DLOG("begin_transaction", "called before db_init");
}
/*
** if we get here we have a corrupt db connection,
** but we probably have a valid db_con_t structure.
** attempt to open the db.
*/
if((rv = connect_db(_h, CON_SQLURL(_h))) != 0)
{
/*
** our attempt to fix the connection failed
*/
char buf[256];
sprintf(buf, "no connection, FATAL %d!", rv);
PLOG("begin_transaction",buf);
return(rv);
}
}
else
{
PLOG("begin_transaction","must call db_init first!");
return(-1);
}
/*
** we get here if the database connection was corrupt,
** i didn't want to use recursion ...
*/
mr = PQexec(CON_CONNECTION(_h), "BEGIN");
if(!mr || PQresultStatus(mr) != PGRES_COMMAND_OK)
{
char buf[256];
sprintf("FATAL %s, '%s'!\n",
PQerrorMessage(CON_CONNECTION(_h)), _s);
PLOG("begin_transaction", buf);
return(-1);
}
DLOG("begin_transaction", "db channel reset successful");
PQclear(mr);
return(0);
}
开发者ID:OPSF,项目名称:uClinux,代码行数:89,代码来源:dbase.c
示例8: darkkernel_bdd_execute
/**
* query = select * from pg_database
*/
char darkkernel_bdd_execute(bdd *self,char *query)
{
PGresult *res;
char portal[1000],result=1;
int nFields;
int i,
j;
if (!self->conn)
self->connect(self);
if (!self->conn)
return 0;
/* Start a transaction block */
res = PQexec(self->conn, "BEGIN");
if (PQresultStatus(res) != PGRES_COMMAND_OK)
{
fprintf(stderr, "BEGIN command failed: %s", PQerrorMessage(self->conn));
PQclear(res);
self->disconnect(self);
result=0;
}
PQclear(res);
/*
* Fetch rows from pg_database, the system catalog of databases
*/
sprintf(portal, "DECLARE myportal CURSOR FOR %s\0", query);
res = PQexec(self->conn, portal);
if (PQresultStatus(res) != PGRES_COMMAND_OK)
{
fprintf(stderr, "DECLARE CURSOR failed: %s", PQerrorMessage(self->conn));
PQclear(res);
PQfinish(self->conn);
}
PQclear(res);
res = PQexec(self->conn, "FETCH ALL in myportal");
if (PQresultStatus(res) != PGRES_TUPLES_OK)
{
fprintf(stderr, "FETCH ALL failed: %s", PQerrorMessage(self->conn));
PQclear(res);
PQfinish(self->conn);
}
/* first, print out the attribute names */
nFields = PQnfields(res);
for (i = 0; i < nFields; i++)
printf("%-15s", PQfname(res, i));
printf("\n\n");
/* next, print out the rows */
for (i = 0; i < PQntuples(res); i++)
{
for (j = 0; j < nFields; j++)
printf("%-15s", PQgetvalue(res, i, j));
printf("\n");
}
PQclear(res);
/* close the portal ... we don't bother to check for errors ... */
res = PQexec(self->conn, "CLOSE myportal");
PQclear(res);
/* end the transaction */
res = PQexec(self->conn, "END");
PQclear(res);
self->disconnect(self);
return result;
}
/*
* 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;
}
/*
* 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;
}
//.........这里部分代码省略.........
请发表评论