/* wydawca - automatic release submission daemon Copyright (C) 2007, 2010-2013 Sergey Poznyakoff Wydawca 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 of the License, or (at your option) any later version. Wydawca 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. You should have received a copy of the GNU General Public License along with wydawca. If not, see . */ #include "wydawca.h" #include "sql.h" /* Singly-linked list of configured MySQL connections. */ struct sql_list { struct sql_list *next; struct sqlconn conn; }; static struct sql_list *sql_list; /* Append CONN to the end of sql_list */ void sql_register_conn(struct sqlconn *conn) { struct sql_list *ent = grecs_malloc(sizeof *ent); ent->conn = *conn; ent->next = sql_list; sql_list = ent; } /* Find a configured connection that has the given IDENT */ struct sqlconn * sql_find_connection(const char *ident) { struct sql_list *p; for (p = sql_list; p; p = p->next) if (strcmp(p->conn.ident, ident) == 0) return &p->conn; return NULL; } /* Return true if there exists a connection with the given IDENT */ int sql_connection_exists_p(const char *ident) { return sql_find_connection(ident) != NULL; } /* Initialize MySQL dictionary */ int sql_init_dictionary(struct dictionary *dict) { struct sqlconn *conn = sql_find_connection(dict->parmv[0]); if (!conn) { wy_log(LOG_EMERG, _("INTERNAL ERROR: cannot find SQL connection %s"), dict->parmv[0]); abort(); } if (conn->initcount++ == 0) { mysql_init(&conn->mysql); if (conn->config_file) mysql_options(&conn->mysql, MYSQL_READ_DEFAULT_FILE, conn->config_file); if (conn->config_group) mysql_options(&conn->mysql, MYSQL_READ_DEFAULT_GROUP, conn->config_group); if (conn->cacert) mysql_ssl_set(&conn->mysql, NULL, NULL, conn->cacert, NULL, NULL); if (!mysql_real_connect(&conn->mysql, conn->host, conn->user, conn->password, conn->database, conn->port, conn->socket, CLIENT_MULTI_RESULTS)) { wy_log(LOG_ERR, _("failed to connect to database %s: " "error: %s\n"), dict->parmv[0], mysql_error(&conn->mysql)); return 1; } } dict->storage = conn; return 0; } void * sql_open(struct dictionary *dict) { return dict->storage; } int sql_free_result(struct dictionary *dict, void *handle) { struct sqlconn *conn = handle; if (conn->result) { mysql_free_result(conn->result); conn->result = NULL; } return 0; } /* Finish the initialized MySQL dictionary */ int sql_done_dictionary(struct dictionary *dict) { struct sqlconn *conn = dict->storage; if (!conn || conn->initcount == 0) return 0; if (--conn->initcount) return 0; sql_free_result(dict, conn); /* FIXME: Not needed */ mysql_close(&conn->mysql); dict->storage = NULL; return 0; } /* Execute QUERY using the given access METHOD. Return 0 on success. */ int sql_lookup_dictionary(struct dictionary *dict, void *handle, const char *query) { struct sqlconn *conn = handle; MYSQL *mysql = &conn->mysql; if (!query) { wy_log(LOG_ERR, _("no query supplied for dictionary %s"), "sql"); return 1; } if (mysql_query(mysql, query)) { wy_log(LOG_ERR, _("query failed: %s"), mysql_error(mysql)); wy_log(LOG_NOTICE, _("the failed query was: %s"), query); return 1; } conn->result = mysql_store_result(mysql); if (!conn->result) { wy_log(LOG_ERR, _("cannot get result: %s"), mysql_error(mysql)); wy_log(LOG_NOTICE, _("the failed query was: %s"), query); return 1; } dict->nrow = mysql_num_rows(conn->result); dict->ncol = mysql_num_fields(conn->result); if (wy_debug_level > 1) { wy_log(LOG_DEBUG, _("query returned %u columns in %u rows"), dict->ncol, dict->nrow); wy_log(LOG_DEBUG, _("the query was: %s"), query); } return 0; } int sql_get_dictionary(struct dictionary *dict, void *handle, unsigned nrow, unsigned ncol) { struct sqlconn *conn = handle; MYSQL_ROW row; size_t len; if (!conn->result) return 1; mysql_data_seek(conn->result, nrow); row = mysql_fetch_row(conn->result); if (row[ncol] == NULL) len = 0; else len = trim_length(row[ncol]); dictionary_copy_result(dict, row[ncol], len); return 0; } int sql_quote(struct dictionary *dict, void *handle, const char *input, char **poutput, size_t * psize) { struct sqlconn *conn = handle; size_t len, size; char *output; len = strlen(input); size = 2 * len + 1; output = grecs_malloc(size); mysql_real_escape_string(&conn->mysql, output, input, len); *poutput = output; if (psize) *psize = strlen(output); return 0; }