The following commit has been merged in the master branch:
commit 466f8db7c0ae73aece67773e3024561153b195f8
Author: Michal Čihař <mci...@novell.com>
Date:   Thu Mar 3 11:16:16 2011 +0100

    Start implementation of ODBC driver.
    
    Only basic stub for now, probably not working.

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 653d470..ae50f7f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -240,6 +240,7 @@ endif (PYTHON_EXECUTABLE)
 
 # Packages in sources
 macro_optional_find_package (MySQL)
+macro_optional_find_package (ODBC)
 macro_optional_find_package (Postgres)
 macro_optional_find_package (LibDBI)
 macro_optional_find_package (Libintl)
diff --git a/cmake/FindODBC.cmake b/cmake/FindODBC.cmake
new file mode 100644
index 0000000..077baec
--- /dev/null
+++ b/cmake/FindODBC.cmake
@@ -0,0 +1,21 @@
+# Find ODBC (or UnixODBC)
+
+find_path(ODBC_INCLUDE_DIR NAMES sql.h
+          DOC "The ODBC include directory"
+)
+
+find_library(ODBC_LIBRARY NAMES odbc odbc32
+          DOC "The ODBC library"
+)
+
+# handle the QUIETLY and REQUIRED arguments and set ODBC_FOUND to TRUE if 
+# all listed variables are TRUE
+include(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(ODBC DEFAULT_MSG ODBC_LIBRARY 
ODBC_INCLUDE_DIR)
+
+if(ODBC_FOUND)
+  set( ODBC_LIBRARIES ${ODBC_LIBRARY} )
+  set( ODBC_INCLUDE_DIRS ${ODBC_INCLUDE_DIR} )
+endif(ODBC_FOUND)
+
+mark_as_advanced(ODBC_INCLUDE_DIR ODBC_LIBRARY)
diff --git a/cmake/templates/gammu-config.h.cmake 
b/cmake/templates/gammu-config.h.cmake
index 891a736..279e48a 100644
--- a/cmake/templates/gammu-config.h.cmake
+++ b/cmake/templates/gammu-config.h.cmake
@@ -172,6 +172,8 @@
 #ifndef HAVE_MYSQL_MYSQL_H
 #cmakedefine HAVE_MYSQL_MYSQL_H
 #endif
+/* ODBC support */
+#cmakedefine ODBC_FOUND
 /* Do we have libdbi ? */
 #cmakedefine LIBDBI_FOUND
 #ifndef HAVE_POSTGRESQL_LIBPQ_FE_H
diff --git a/smsd/CMakeLists.txt b/smsd/CMakeLists.txt
index 146d170..7e52955 100644
--- a/smsd/CMakeLists.txt
+++ b/smsd/CMakeLists.txt
@@ -12,9 +12,9 @@ set (LIBRARY_SRC
     services/null.c
     )
 
-if (HAVE_MYSQL_MYSQL_H OR LIBDBI_FOUND OR HAVE_POSTGRESQL_LIBPQ_FE_H)
+if (HAVE_MYSQL_MYSQL_H OR LIBDBI_FOUND OR HAVE_POSTGRESQL_LIBPQ_FE_H OR 
ODBC_FOUND)
     list(APPEND LIBRARY_SRC services/sql.c)
-endif (HAVE_MYSQL_MYSQL_H OR LIBDBI_FOUND OR HAVE_POSTGRESQL_LIBPQ_FE_H)
+endif (HAVE_MYSQL_MYSQL_H OR LIBDBI_FOUND OR HAVE_POSTGRESQL_LIBPQ_FE_H OR 
ODBC_FOUND)
 
 if (HAVE_MYSQL_MYSQL_H)
     list(APPEND LIBRARY_SRC services/mysql.c)
@@ -28,6 +28,10 @@ if (LIBDBI_FOUND)
     list(APPEND LIBRARY_SRC services/dbi.c)
 endif (LIBDBI_FOUND)
 
+if (ODBC_FOUND)
+    list(APPEND LIBRARY_SRC services/odbc.c)
+endif (ODBC_FOUND)
+
 if (WIN32)
     list(APPEND LIBRARY_SRC log-event.c)
 endif (WIN32)
@@ -114,6 +118,11 @@ if (LIBDBI_FOUND)
     include_directories (${LIBDBI_INCLUDE_DIR})
 endif (LIBDBI_FOUND)
 
+if (ODBC_FOUND)
+    target_link_libraries (gsmsd ${ODBC_LIBRARIES})
+    include_directories (${ODBC_INCLUDE_DIR})
+endif (ODBC_FOUND)
+
 if (MYSQL_FOUND)
     target_link_libraries (gsmsd ${MYSQL_LIBRARIES})
     include_directories (${MYSQL_INCLUDE_DIR})
diff --git a/smsd/services/odbc.c b/smsd/services/odbc.c
new file mode 100644
index 0000000..1a9586a
--- /dev/null
+++ b/smsd/services/odbc.c
@@ -0,0 +1,206 @@
+/**
+ * ODBC database backend
+ *
+ * Part of Gammu project
+ *
+ * Copyright (C) 2011 Michal Čihař
+ *
+ * Licensed under GNU GPL version 2 or later
+ */
+
+#include <gammu.h>
+
+#ifdef WIN32
+#include <windows.h>
+#ifndef __GNUC__
+#pragma comment(lib, "libodbc32.lib")
+#endif
+#endif
+
+#include <stdio.h>
+#include <sql.h>
+#include <sqlext.h>
+
+#include "../core.h"
+#include "sql.h"
+#include "sql-core.h"
+
+long long SMSDODBC_GetNumber(GSM_SMSDConfig * Config, SQL_result rc, unsigned 
int field)
+{
+       /* TODO */
+       return -1;
+}
+
+time_t SMSDODBC_GetDate(GSM_SMSDConfig * Config, SQL_result rc, unsigned int 
field)
+{
+       /* TODO */
+       return -1;
+}
+
+gboolean SMSDODBC_GetBool(GSM_SMSDConfig * Config, SQL_result rc, unsigned int 
field)
+{
+       /* TODO */
+       return -1;
+}
+
+const char *SMSDODBC_GetString(GSM_SMSDConfig * Config, SQL_result res, 
unsigned int col)
+{
+       /* TODO */
+       return NULL;
+}
+
+static void SMSDODBC_LogError(GSM_SMSDConfig * Config, SQLSMALLINT 
handle_type, SQLHANDLE handle, const char *message)
+{
+       SQLINTEGER       i = 0;
+       SQLINTEGER       native;
+       SQLCHAR  state[ 7 ];
+       SQLCHAR  text[256];
+       SQLSMALLINT      len;
+       SQLRETURN        ret;
+
+       SMSD_Log(DEBUG_ERROR, Config, "%s, ODBC diagnostics:", message);
+
+       do {
+               ret = SQLGetDiagRec(handle_type, handle, ++i, state, &native, 
text, sizeof(text), &len );
+               if (SQL_SUCCEEDED(ret)) {
+                       SMSD_Log(DEBUG_ERROR, Config, "%s:%ld:%ld:%s\n", state, 
(long)i, (long)native, text);
+               }
+       } while (ret == SQL_SUCCESS);
+}
+
+/* Disconnects from a database */
+void SMSDODBC_Free(GSM_SMSDConfig * Config)
+{
+       SQLDisconnect(Config->conn.odbc.dbc);
+       SQLFreeHandle(SQL_HANDLE_ENV, Config->conn.odbc.env);
+}
+
+/* Connects to database */
+static SQL_Error SMSDODBC_Connect(GSM_SMSDConfig * Config)
+{
+       SQLRETURN ret;
+
+       ret = SQLAllocHandle (SQL_HANDLE_ENV, SQL_NULL_HANDLE, 
&Config->conn.odbc.env);
+       if (!SQL_SUCCEEDED(ret)) {
+               SMSDODBC_LogError(Config, SQL_HANDLE_ENV, 
Config->conn.odbc.env, "SQLAllocHandle failed");
+               return SQL_FAIL;
+       }
+
+       ret = SQLSetEnvAttr (Config->conn.odbc.env, SQL_ATTR_ODBC_VERSION, 
(void*)SQL_OV_ODBC3, 0);
+       if (!SQL_SUCCEEDED(ret)) {
+               SMSDODBC_LogError(Config, SQL_HANDLE_ENV, 
Config->conn.odbc.env, "SQLSetEnvAttr failed");
+               return SQL_FAIL;
+       }
+
+       ret = SQLAllocHandle (SQL_HANDLE_DBC, Config->conn.odbc.env, 
&Config->conn.odbc.dbc);
+       if (!SQL_SUCCEEDED(ret)) {
+               SMSDODBC_LogError(Config, SQL_HANDLE_ENV, 
Config->conn.odbc.env, "SQLAllocHandle failed");
+               return SQL_FAIL;
+       }
+
+       ret = SQLConnect(Config->conn.odbc.dbc,
+                         (SQLCHAR*)Config->host, SQL_NTS,
+                         (SQLCHAR*)Config->user, SQL_NTS,
+                         (SQLCHAR*)Config->password, SQL_NTS);
+       if (!SQL_SUCCEEDED(ret)) {
+               SMSDODBC_LogError(Config, SQL_HANDLE_DBC, 
Config->conn.odbc.dbc, "SQLAllocHandle failed");
+               return SQL_FAIL;
+       }
+
+       return SQL_OK;
+}
+
+static SQL_Error SMSDODBC_Query(GSM_SMSDConfig * Config, const char *query, 
SQL_result * res)
+{
+       SQLRETURN ret;
+
+       ret = SQLAllocHandle(SQL_HANDLE_STMT, Config->conn.odbc.dbc, 
&res->odbc);
+       if (!SQL_SUCCEEDED(ret)) {
+               return SQL_FAIL;
+       }
+
+       ret = SQLExecDirect (res->odbc, (SQLCHAR*)query, SQL_NTS);
+       if (SQL_SUCCEEDED(ret)) {
+               return SQL_OK;
+       }
+
+       return SQL_FAIL;
+}
+
+/* free sql results */
+void SMSDODBC_FreeResult(GSM_SMSDConfig * Config, SQL_result res)
+{
+       SQLFreeHandle (SQL_HANDLE_STMT, res.odbc);
+}
+
+/* set pointer to next row */
+int SMSDODBC_NextRow(GSM_SMSDConfig * Config, SQL_result *res)
+{
+       SQLRETURN ret;
+
+       ret = SQLFetch(res->odbc);
+
+       return SQL_SUCCEEDED(ret);
+}
+
+/* quote strings */
+char * SMSDODBC_QuoteString(GSM_SMSDConfig * Config, SQL_conn *conn, const 
char *string)
+{
+       char *encoded_text = NULL;
+       /* TODO: implement escaping */
+       encoded_text = strdup(string);
+       return encoded_text;
+}
+
+/* LAST_INSERT_ID */
+unsigned long long SMSDODBC_SeqID(GSM_SMSDConfig * Config, const char *id)
+{
+       /* TODO */
+       return 0;
+}
+
+unsigned long SMSDODBC_AffectedRows(GSM_SMSDConfig * Config, SQL_result res)
+{
+       SQLRETURN ret;
+       SQLLEN count;
+
+       ret = SQLRowCount (res.odbc, &count);
+       if (!SQL_SUCCEEDED(ret)) {
+               SMSDODBC_LogError(Config, SQL_HANDLE_DBC, 
Config->conn.odbc.dbc, "SQLRowCount failed");
+               return 0;
+       }
+       return count;
+}
+
+unsigned long SMSDODBC_NumRows(GSM_SMSDConfig * Config, SQL_result Res)
+{
+       SQLRETURN ret;
+
+       /* FIXME: This is hack relying on sql.c not using anything else than 0 
and 1 as values */
+       ret = SQLMoreResults(Res.odbc);
+       if (SQL_SUCCEEDED(ret)) {
+               return 1;
+       }
+       return 0;
+}
+
+struct GSM_SMSDdbobj SMSDODBC = {
+       "",
+       SMSDODBC_Connect,
+       SMSDODBC_Query,
+       SMSDODBC_Free,
+       SMSDODBC_FreeResult,
+       SMSDODBC_NextRow,
+       SMSDODBC_SeqID,
+       SMSDODBC_AffectedRows,
+       SMSDODBC_NumRows,
+       SMSDODBC_GetString,
+       SMSDODBC_GetNumber,
+       SMSDODBC_GetDate,
+       SMSDODBC_GetBool,
+       SMSDODBC_QuoteString,
+};
+
+/* How should editor hadle tabs in this file? Add editor commands here.
+ * vim: noexpandtab sw=8 ts=8 sts=8:
+ */
diff --git a/contrib/smscgi/gammulog b/smsd/services/odbc.h
similarity index 100%
copy from contrib/smscgi/gammulog
copy to smsd/services/odbc.h
diff --git a/smsd/services/sql-core.h b/smsd/services/sql-core.h
index 486ddd3..b8ab951 100644
--- a/smsd/services/sql-core.h
+++ b/smsd/services/sql-core.h
@@ -30,6 +30,11 @@
 #include <sys/types.h>
 #endif
 
+#ifdef ODBC_FOUND
+#include <sql.h>
+#include <sqlext.h>
+#endif
+
 /* sql result structures */
 typedef union {
 #ifdef LIBDBI_FOUND
@@ -48,6 +53,9 @@ typedef union {
                int iter; /* libpq does not have nexrow .. */
        } pg;
 #endif
+#ifdef ODBC_FOUND
+       SQLHSTMT odbc;      /* Statement being executed */
+#endif
 } SQL_result;
 
 /* sql connection structures */
@@ -61,6 +69,12 @@ typedef union __sql_conn {
 #ifdef HAVE_POSTGRESQL_LIBPQ_FE_H
        PGconn *pg; /* pgsql driver */
 #endif
+#ifdef ODBC_FOUND
+       struct {
+               SQLHENV env;        /* Environment */
+               SQLHDBC dbc;        /* DBC */
+       } odbc;
+#endif
 } SQL_conn;
 
 /* SQL errors */
@@ -148,6 +162,10 @@ extern struct GSM_SMSDdbobj SMSDMySQL;
 #ifdef LIBDBI_FOUND
 extern struct GSM_SMSDdbobj SMSDDBI;
 #endif
+
+#ifdef ODBC_FOUND
+extern struct GSM_SMSDdbobj SMSDODBC;
+#endif
 #endif
 
 /* How should editor hadle tabs in this file? Add editor commands here.
diff --git a/smsd/services/sql.c b/smsd/services/sql.c
index 350de50..c90ca2b 100644
--- a/smsd/services/sql.c
+++ b/smsd/services/sql.c
@@ -1016,7 +1016,7 @@ GSM_Error SMSDSQL_ReadConfiguration(GSM_SMSDConfig 
*Config)
        Config->dbdir = INI_GetValue(Config->smsdcfgfile, "smsd", "dbdir", 
FALSE);
 
        if (Config->driver == NULL) {
-               SMSD_Log(DEBUG_ERROR, Config, "No database driver selected. 
Must be native_mysql, native_pgsql or DBI one.");
+               SMSD_Log(DEBUG_ERROR, Config, "No database driver selected. 
Must be native_mysql, native_pgsql, ODBC or DBI one.");
                return ERR_UNKNOWN;
        }
 
@@ -1029,6 +1029,10 @@ GSM_Error SMSDSQL_ReadConfiguration(GSM_SMSDConfig 
*Config)
        if (!strcasecmp(Config->driver, "native_pgsql"))
                Config->db = &SMSDPgSQL;
 #endif
+#ifdef ODBC_FOUND
+       if (!strcasecmp(Config->driver, "odbc"))
+               Config->db = &SMSDODBC;
+#endif
        if (Config->db == NULL) {
 #ifdef LIBDBI_FOUND
                Config->db = &SMSDDBI;

-- 
Gammu

_______________________________________________
Gammu-svn mailing list
Gammu-svn@lists.cihar.com
https://lists.cihar.com/cgi-bin/mailman/listinfo/gammu-svn

Reply via email to