/* This file is part of guile-sql. Copyright (C) 2002 Sergey Poznyakoff This program 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 2 of the License, or (at your option) any later version. This program 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 this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include int num_iface; struct sql_iface sql_iftab[MAX_IFACES]; long sql_connect_tag; /* SMOB functions: */ static SCM sql_connect_mark (SCM connect_smob) { struct sql_connect *conn = (struct sql_connect *)SCM_CDR(connect_smob); return sql_iftab[conn->iface].mark(conn); } static scm_sizet sql_connect_free (SCM connect_smob) { scm_sizet size = sizeof(struct sql_connect); struct sql_connect *conn = (struct sql_connect *)SCM_CDR(connect_smob); size += sql_iftab[conn->iface].free(conn); if (conn->hostname) free(conn->hostname); if (conn->username) free(conn->username); if (conn->database) free(conn->database); free(conn); return size; } static int sql_connect_print (SCM connect_smob, SCM port, scm_print_state * pstate) { struct sql_connect *conn = (struct sql_connect *)SCM_CDR(connect_smob); scm_puts("#iface].name, port); scm_puts(")", port); if (!conn->data) scm_puts("not connected", port); else { scm_puts(conn->username, port); scm_puts("@", port); scm_puts(conn->hostname, port); scm_puts(":", port); scm_intprint(conn->port, 10, port); scm_puts(" ", port); scm_puts(conn->database, port); }; scm_puts (">", port); return 1; } int sql_find_iface(char *name) { int iface; for (iface = 0; iface < num_iface; iface++) if (strcmp(sql_iftab[iface].name, name) == 0) return iface; return -1; } SCM sql_connect_create (char *name) { struct sql_connect *conn; int iface = sql_find_iface(name); if (iface < 0) scm_misc_error("sql_connect_create", "Unknown SQL interface ~S", SCM_LIST1(scm_makfrom0str(name))); conn = scm_must_malloc (sizeof (*conn), "sql_connect"); memset(conn, 0, sizeof *conn); conn->iface = iface; SCM_RETURN_NEWSMOB (sql_connect_tag, conn); } int scm_is_sql_connect (SCM scm) { return SCM_NIMP (scm) && SCM_CAR (scm) == sql_connect_tag; } /* Interface */ SCM_DEFINE (sql_connect, "sql-connect", 5, 1, 0, (SCM IFACE, SCM HOST, SCM PORT, SCM DB, SCM USER, SCM PASS), "Connect to a database.") #define FUNC_NAME s_sql_connect { SCM smob; char *hostname; int port; char *dbname; char *user; char *pass; int iface; if (SCM_IMP(IFACE) && SCM_INUMP(IFACE)) iface = SCM_INUM(IFACE); else if (SCM_STRINGP(IFACE)) iface = sql_find_iface(SCM_CHARS(IFACE)); else { SCM_ASSERT(IFACE == SCM_BOOL_T || IFACE == SCM_BOOL_F, IFACE, SCM_ARG1, FUNC_NAME); iface = 0; } if (iface < 0 || iface >= num_iface) scm_misc_error(FUNC_NAME, "Argument ~S (~S) out of range", SCM_LIST2(SCM_MAKINUM(1), IFACE)); SCM_ASSERT(SCM_STRINGP(HOST), HOST, SCM_ARG1, FUNC_NAME); hostname = SCM_ROCHARS(HOST); SCM_ASSERT(SCM_IMP(PORT) && SCM_INUMP(PORT), PORT, SCM_ARG2, FUNC_NAME); port = SCM_INUM(PORT); SCM_ASSERT(SCM_STRINGP(DB), DB, SCM_ARG3, FUNC_NAME); dbname = SCM_ROCHARS(DB); SCM_ASSERT(SCM_STRINGP(USER), USER, SCM_ARG4, FUNC_NAME); user = SCM_ROCHARS(USER); if (SCM_UNBNDP(PASS)) pass = NULL; else if (SCM_STRINGP(USER)) pass = SCM_ROCHARS(PASS); smob = sql_iftab[iface].connect(hostname, port, dbname, user, pass, FUNC_NAME); if (smob != SCM_BOOL_F) { struct sql_connect *conn = (struct sql_connect *)SCM_CDR(smob); conn->hostname = strdup(hostname); conn->port = port; conn->username = strdup(user); conn->database = strdup(dbname); } return smob; } #undef FUNC_NAME SCM_DEFINE (sql_connect_close, "sql-connect-close", 1, 0, 0, (SCM CONN), "Close connection to a database.") #define FUNC_NAME s_sql_connect_close { struct sql_connect *conn; SCM_ASSERT(scm_is_sql_connect(CONN), CONN, SCM_ARG1, FUNC_NAME); conn = (struct sql_connect *)SCM_CDR(CONN); sql_iftab[conn->iface].close(conn); return SCM_UNSPECIFIED; } #undef FUNC_NAME SCM_DEFINE (sql_query, "sql-query", 2, 0, 0, (SCM CONN, SCM QUERY), "Run an SQL query") #define FUNC_NAME s_sql_query { struct sql_connect *conn; void *ptr; char *query; SCM_ASSERT(scm_is_sql_connect(CONN), CONN, SCM_ARG1, FUNC_NAME); SCM_ASSERT(SCM_STRINGP(QUERY), QUERY, SCM_ARG2, FUNC_NAME); conn = (struct sql_connect *)SCM_CDR(CONN); query = SCM_ROCHARS(QUERY); return sql_iftab[conn->iface].query(conn, query); } #undef FUNC_NAME int sql_register_iface(struct sql_iface *ifp) { if (num_iface >= MAX_IFACES) scm_misc_error("sql_register_iface", "Too many ifaces registered", SCM_EOL); memcpy(&sql_iftab[num_iface], ifp, sizeof sql_iftab[0]); sql_iftab[num_iface].name = strdup(ifp->name); return num_iface++; } void gsql_conn_init() { sql_connect_tag = scm_make_smob_type ("sql_connect", sizeof (struct sql_connect)); scm_set_smob_mark (sql_connect_tag, sql_connect_mark); scm_set_smob_free (sql_connect_tag, sql_connect_free); scm_set_smob_print (sql_connect_tag, sql_connect_print); #ifndef SCM_MAGIC_SNARFER # include #endif }