This file is part of GNUnet
Copyright (C) 2017 GNUnet e.V.
- GNUnet is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
- Foundation; either version 3, or (at your option) any later version.
+ GNUnet is free software: you can redistribute it and/or modify it
+ under the terms of the GNU Affero General Public License as published
+ by the Free Software Foundation, either version 3 of the License,
+ or (at your option) any later version.
- GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Affero General Public License for more details.
- You should have received a copy of the GNU General Public License along with
- GNUnet; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ SPDX-License-Identifier: AGPL3.0-or-later
*/
/**
* @file pq/pq_eval.c
* @param statement_name name of the statement that created @a result
* @param result result to check
* @return status code from the result, mapping PQ status
- * codes to `enum GNUNET_PQ_QueryStatus`. Never
+ * codes to `enum GNUNET_DB_QueryStatus`. Never
* returns positive values as this function does
* not look at the result set.
* @deprecated (low level, let's see if we can do with just the high-level functions)
*/
-enum GNUNET_PQ_QueryStatus
+enum GNUNET_DB_QueryStatus
GNUNET_PQ_eval_result (PGconn *connection,
const char *statement_name,
PGresult *result)
{
/* very unexpected... */
GNUNET_break (0);
- return GNUNET_PQ_STATUS_HARD_ERROR;
+ return GNUNET_DB_STATUS_HARD_ERROR;
}
if ( (0 == strcmp (sqlstate,
PQ_DIAG_SQLSTATE_DEADLOCK)) ||
PQresultErrorMessage (result),
PQresStatus (PQresultStatus (result)),
PQerrorMessage (connection));
- return GNUNET_PQ_STATUS_SOFT_ERROR;
+ return GNUNET_DB_STATUS_SOFT_ERROR;
+ }
+ if (0 == strcmp (sqlstate,
+ PQ_DIAG_SQLSTATE_UNIQUE_VIOLATION))
+ {
+ /* Likely no need to retry, INSERT of "same" data. */
+ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
+ "pq",
+ "Query `%s' failed with unique violation: %s/%s/%s/%s/%s\n",
+ statement_name,
+ PQresultErrorField (result,
+ PG_DIAG_MESSAGE_PRIMARY),
+ PQresultErrorField (result,
+ PG_DIAG_MESSAGE_DETAIL),
+ PQresultErrorMessage (result),
+ PQresStatus (PQresultStatus (result)),
+ PQerrorMessage (connection));
+ return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
}
GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR,
"pq",
PQresultErrorMessage (result),
PQresStatus (PQresultStatus (result)),
PQerrorMessage (connection));
- return GNUNET_PQ_STATUS_HARD_ERROR;
+ return GNUNET_DB_STATUS_HARD_ERROR;
}
- return GNUNET_PQ_STATUS_SUCCESS_NO_RESULTS;
+ return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
}
* @param statement_name name of the statement
* @param params parameters to give to the statement (#GNUNET_PQ_query_param_end-terminated)
* @return status code from the result, mapping PQ status
- * codes to `enum GNUNET_PQ_QueryStatus`. Never
- * returns positive values as this function does
- * not look at the result set.
+ * codes to `enum GNUNET_DB_QueryStatus`. If the
+ * statement was a DELETE or UPDATE statement, the
+ * number of affected rows is returned.; if the
+ * statment was an INSERT statement, and no row
+ * was added due to a UNIQUE violation, we return
+ * zero; if INSERT was successful, we return one.
*/
-enum GNUNET_PQ_QueryStatus
+enum GNUNET_DB_QueryStatus
GNUNET_PQ_eval_prepared_non_select (PGconn *connection,
const char *statement_name,
const struct GNUNET_PQ_QueryParam *params)
{
PGresult *result;
- enum GNUNET_PQ_QueryStatus qs;
+ enum GNUNET_DB_QueryStatus qs;
result = GNUNET_PQ_exec_prepared (connection,
statement_name,
qs = GNUNET_PQ_eval_result (connection,
statement_name,
result);
+ if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
+ {
+ const char *tuples;
+
+ /* What an awful API, this function really does return a string */
+ tuples = PQcmdTuples (result);
+ if (NULL != tuples)
+ qs = strtol (tuples, NULL, 10);
+ }
PQclear (result);
return qs;
}
* @param rh function to call with the result set, NULL to ignore
* @param rh_cls closure to pass to @a rh
* @return status code from the result, mapping PQ status
- * codes to `enum GNUNET_PQ_QueryStatus`.
+ * codes to `enum GNUNET_DB_QueryStatus`.
*/
-enum GNUNET_PQ_QueryStatus
+enum GNUNET_DB_QueryStatus
GNUNET_PQ_eval_prepared_multi_select (PGconn *connection,
const char *statement_name,
const struct GNUNET_PQ_QueryParam *params,
void *rh_cls)
{
PGresult *result;
- enum GNUNET_PQ_QueryStatus qs;
+ enum GNUNET_DB_QueryStatus qs;
unsigned int ret;
result = GNUNET_PQ_exec_prepared (connection,
* which must return a single result in @a connection using the given
* @a params. Stores the result (if any) in @a rs, which the caller
* must then clean up using #GNUNET_PQ_cleanup_result() if the return
- * value was #GNUNET_PQ_STATUS_SUCCESS_ONE_RESULT. Returns the
+ * value was #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT. Returns the
* resulting session status.
*
* @param connection connection to execute the statement in
* @param params parameters to give to the statement (#GNUNET_PQ_query_param_end-terminated)
* @param[in,out] rs result specification to use for storing the result of the query
* @return status code from the result, mapping PQ status
- * codes to `enum GNUNET_PQ_QueryStatus`.
+ * codes to `enum GNUNET_DB_QueryStatus`.
*/
-enum GNUNET_PQ_QueryStatus
+enum GNUNET_DB_QueryStatus
GNUNET_PQ_eval_prepared_singleton_select (PGconn *connection,
const char *statement_name,
const struct GNUNET_PQ_QueryParam *params,
struct GNUNET_PQ_ResultSpec *rs)
{
PGresult *result;
- enum GNUNET_PQ_QueryStatus qs;
+ enum GNUNET_DB_QueryStatus qs;
result = GNUNET_PQ_exec_prepared (connection,
statement_name,
if (0 == PQntuples (result))
{
PQclear (result);
- return GNUNET_PQ_STATUS_SUCCESS_NO_RESULTS;
+ return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
}
if (1 != PQntuples (result))
{
/* more than one result, but there must be at most one */
GNUNET_break (0);
PQclear (result);
- return GNUNET_PQ_STATUS_HARD_ERROR;
+ return GNUNET_DB_STATUS_HARD_ERROR;
}
if (GNUNET_OK !=
GNUNET_PQ_extract_result (result,
0))
{
PQclear (result);
- return GNUNET_PQ_STATUS_HARD_ERROR;
+ return GNUNET_DB_STATUS_HARD_ERROR;
}
PQclear (result);
- return GNUNET_PQ_STATUS_SUCCESS_ONE_RESULT;
+ return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
}