diff options
Diffstat (limited to 'src/mysql.c')
-rw-r--r-- | src/mysql.c | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/src/mysql.c b/src/mysql.c new file mode 100644 index 0000000..8491bb4 --- /dev/null +++ b/src/mysql.c @@ -0,0 +1,131 @@ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif +#include <string.h> +#include <guile-sql.h> +#include <mysql/mysql.h> + +SCM +s_mysql_mark(struct sql_connect *conn) +{ + return SCM_BOOL_F; +} + +scm_sizet +s_mysql_free(struct sql_connect *conn) +{ + MYSQL *mysql = (MYSQL*) conn->data; + if (!mysql) + return 0; + mysql_close(mysql); + free(mysql); + return sizeof(MYSQL); +} + +SCM +s_mysql_connect (char *hostname, int port, + char *dbname, char *user, char *pass, char *why) +{ + MYSQL *mysql; + SCM smob; + struct sql_connect *conn; + + mysql = mysql_init(NULL); + if (!mysql) + return SCM_BOOL_F; + if (!mysql_real_connect(mysql, hostname, + user, pass, dbname, + port, NULL, 0)) { + mysql_close(mysql); + return SCM_BOOL_F; + } + + smob = sql_connect_create("mysql"); + conn = (struct sql_connect *)SCM_CDR(smob); + conn->data = mysql; + return smob; +} + +SCM +s_mysql_query(struct sql_connect *conn, char *query) +{ + MYSQL *mysql = conn->data; + MYSQL_RES *result; + SCM cell; + + if (mysql_query(mysql, query)) + scm_misc_error("s_mysql_query", + "MySQL error: ~S", + SCM_LIST1(scm_makfrom0str(mysql_error(mysql)))); + + 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; + + for (i = 0; i < nrows; i++) { + SCM new_row; + SCM head = SCM_EOL, tail; + MYSQL_ROW row = mysql_fetch_row(result); + + if (!row) + break; + for (j = 0; j < nfields; j++) { + SCM new_elt; + SCM_NEWCELL(new_elt); + SCM_SETCAR(new_elt, scm_makfrom0str(row[j])); + if (head == SCM_EOL) + head = new_elt; + else + SCM_SETCDR(tail, new_elt); + tail = new_elt; + } + + if (head != SCM_EOL) + SCM_SETCDR(tail, SCM_EOL); + + SCM_NEWCELL(new_row); + SCM_SETCAR(new_row, head); + + if (row_head == SCM_EOL) + row_head = new_row; + else + SCM_SETCDR(row_tail, new_row); + row_tail = new_row; + } + if (row_head != SCM_EOL) + SCM_SETCDR(row_tail, SCM_EOL); + cell = row_head; + mysql_free_result(result); + } else { /* should it have returned something? */ + if (mysql_field_count(mysql) == 0) { + cell = scm_makenum(mysql_affected_rows(mysql)); + } else { /* mysql_store_result() should have returned data */ + scm_misc_error("s_mysql_query", + "MySQL error: ~S", + SCM_LIST1(scm_makfrom0str(mysql_error(mysql)))); + } + } + return cell; +} + +void +s_mysql_close(struct sql_connect *conn) +{ + if (conn->data) + mysql_close(conn->data); + conn->data = NULL; +} + +struct sql_iface mysql_iface = { + "mysql", + s_mysql_mark, + s_mysql_free, + s_mysql_connect, + s_mysql_close, + s_mysql_query, +}; + |