aboutsummaryrefslogtreecommitdiff
path: root/gamma/mysql.c
diff options
context:
space:
mode:
Diffstat (limited to 'gamma/mysql.c')
-rw-r--r--gamma/mysql.c227
1 files changed, 227 insertions, 0 deletions
diff --git a/gamma/mysql.c b/gamma/mysql.c
new file mode 100644
index 0000000..dcc1847
--- /dev/null
+++ b/gamma/mysql.c
@@ -0,0 +1,227 @@
+/* This file is part of Gamma.
+ Copyright (C) 2002, 2004, 2005, 2010 Sergey Poznyakoff
+
+ Gamma 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.
+
+ Gamma 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 Gamma. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <string.h>
+#include <guile-sql.h>
+#include <mysql/mysql.h>
+
+static size_t
+s_mysql_free(struct sql_connect *conn)
+{
+ MYSQL *mysql = (MYSQL*) conn->data;
+ if (mysql)
+ mysql_close(mysql);
+ return 0;
+}
+
+static SCM
+s_mysql_connect(SCM parmlist, const char *func_name)
+{
+ char *hostname = NULL;
+ int port = 0;
+ char *dbname = NULL;
+ char *user = NULL;
+ char *pass = NULL;
+ char *socket_path = NULL;
+ char *ssl_cert = NULL;
+ char *config_file = NULL;
+ char *config_group = NULL;
+ struct gamma_parmdcl dcltab[] = {
+ { "iface", NULL, NULL },
+ { "host", &hostname, gamma_cvt_string },
+ { "socket", &socket_path, gamma_cvt_string },
+ { "port", &port, gamma_cvt_int },
+ { "db", &dbname, gamma_cvt_string },
+ { "user", &user, gamma_cvt_string },
+ { "pass", &pass, gamma_cvt_string },
+ { "ssl-cert", &ssl_cert, gamma_cvt_string },
+ { "config-file", &config_file, gamma_cvt_string },
+ { "config-group", &config_group, gamma_cvt_string },
+ { NULL }
+ };
+
+ MYSQL *mysql, *mp;
+ SCM smob;
+ struct sql_connect *conn;
+
+ gamma_parmlist_parse (parmlist, dcltab, 0, func_name);
+
+ mysql = mysql_init(NULL);
+
+ if (!mysql)
+ scm_error(gamma_sql_error,
+ func_name,
+ "~A",
+ scm_list_1(scm_from_locale_string("mysql_init() failed")),
+ SCM_BOOL_F);
+
+ if (hostname && hostname[0] == '/') {
+ socket_path = hostname;
+ hostname = strdup ("localhost");
+ }
+
+ if (config_file) {
+ mysql_options (mysql, MYSQL_READ_DEFAULT_FILE, config_file);
+ free(config_file);
+ }
+ if (config_group) {
+ mysql_options (mysql, MYSQL_READ_DEFAULT_GROUP, config_group);
+ free(config_group);
+ }
+ if (ssl_cert) {
+ mysql_ssl_set (mysql, NULL, NULL, ssl_cert, NULL, NULL);
+ free(ssl_cert);
+ }
+
+ mp = mysql_real_connect(mysql, hostname,
+ user, pass, dbname,
+ port, socket_path,
+ CLIENT_MULTI_RESULTS);
+ free(socket_path);
+
+ if (!mp) {
+ SCM args, mdiag;
+
+ free(hostname);
+ free(user);
+ free(pass);
+ free(dbname);
+
+ mdiag = scm_from_locale_string(mysql_error(mysql));
+ args = scm_list_2(scm_from_uint(mysql_errno(mysql)),
+ mdiag);
+ mysql_close(mysql);
+
+ scm_error(gamma_sql_error, func_name,
+ "~A: ~A",
+ scm_list_2(scm_from_locale_string("Cannot connect to the database"), mdiag),
+ args);
+ }
+
+ smob = sql_connect_create("mysql");
+ conn = (struct sql_connect *)SCM_CDR(smob);
+ conn->hostname = hostname;
+ conn->port = port;
+ conn->username = user;
+ conn->database = dbname;
+ conn->data = mysql;
+ return smob;
+}
+
+static void
+flush_result(MYSQL *mysql)
+{
+ while (mysql_next_result(mysql) == 0) {
+ MYSQL_RES *result = mysql_store_result(mysql);
+ if (!result)
+ break;
+ if (mysql_field_count(mysql))
+ while (mysql_fetch_row(result))
+ ;
+ mysql_free_result(result);
+ }
+}
+
+static SCM
+s_mysql_query(struct sql_connect *conn, const char *query)
+{
+ MYSQL *mysql = conn->data;
+ MYSQL_RES *result;
+ SCM cell = SCM_EOL;
+
+ if (mysql_query(mysql, query)) {
+ SCM mdiag = scm_from_locale_string(mysql_error(mysql));
+
+ scm_error(gamma_sql_error, "sql-query",
+ "~A: ~A",
+ scm_list_2(scm_from_locale_string("Error executing MySQL query"),
+ mdiag),
+ scm_list_2(scm_from_uint(mysql_errno(mysql)),
+ mdiag));
+ }
+
+ result = mysql_store_result(mysql);
+
+ if (result) {
+ int nfields = mysql_num_fields(result);
+ int nrows = mysql_num_rows(result);
+ int i, j;
+ SCM row_head = SCM_EOL, row_tail = SCM_EOL;
+
+ for (i = 0; i < nrows; i++) {
+ SCM new_row;
+ SCM head = SCM_EOL, tail = SCM_EOL;
+ MYSQL_ROW row = mysql_fetch_row(result);
+
+ if (!row)
+ break;
+ for (j = 0; j < nfields; j++) {
+ SCM new_elt =
+ scm_cons(row[j] ?
+ scm_from_locale_string(row[j]) :
+ SCM_BOOL_F,
+ SCM_EOL);
+ if (head == SCM_EOL)
+ head = new_elt;
+ else
+ SCM_SETCDR(tail, new_elt);
+ tail = new_elt;
+ }
+
+ new_row = scm_cons(head, SCM_EOL);
+ if (row_head == SCM_EOL)
+ row_head = new_row;
+ else
+ SCM_SETCDR(row_tail, new_row);
+ row_tail = new_row;
+ }
+ cell = row_head;
+ mysql_free_result(result);
+ flush_result(mysql);
+ } else { /* should it have returned something? */
+ if (mysql_field_count(mysql) == 0) {
+ cell = scm_from_ulong(mysql_affected_rows(mysql));
+ } else { /* mysql_store_result() should have returned data */
+ scm_error(gamma_sql_error, "sql-query",
+ "~A",
+ scm_list_1(scm_from_locale_string("Query should have returned data")),
+ scm_list_2(scm_from_uint(mysql_errno(mysql)),
+ scm_from_locale_string(mysql_error(mysql))));
+ }
+ }
+ return cell;
+}
+
+static void
+s_mysql_close(struct sql_connect *conn)
+{
+ if (conn->data)
+ mysql_close(conn->data);
+ conn->data = NULL;
+}
+
+struct sql_iface mysql_iface = {
+ "mysql",
+ NULL, /* mark */
+ s_mysql_free,
+ s_mysql_connect,
+ s_mysql_close,
+ s_mysql_query,
+};
+

Return to:

Send suggestions and report system problems to the System administrator.