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