const char *SMSDODBC_GetString(GSM_SMSDConfig * Config, SQL_result *res, unsigned int field) { SQLLEN sqllen; int size; SQLRETURN ret; char shortbuffer[1]; if (field > SMSD_ODBC_MAX_RETURN_STRINGS) { SMSD_Log(DEBUG_ERROR, Config, "Field %d returning NULL, too many fields!", field); return NULL; } /* Figure out string length */ ret = SQLGetData(res->odbc, field + 1, SQL_C_CHAR, shortbuffer, 0, &sqllen); if (!SQL_SUCCEEDED(ret)) { SMSDODBC_LogError(Config, ret, SQL_HANDLE_STMT, res->odbc, "SQLGetData(string,0) failed"); return NULL; } /* * This hack seems to be needed to avoid type breakage on Win64, don't ask me why. * * Might be actually bug in MinGW compiler, but when using SQLLEN type bellow * anything fails (it does not match to SQL_NULL_DATA and realloc always fails). */ size = sqllen; /* Did not we get NULL? */ if (size == SQL_NULL_DATA) { SMSD_Log(DEBUG_SQL, Config, "Field %d returning NULL", field); return NULL; } /* Allocate string */ Config->conn.odbc.retstr[field] = realloc(Config->conn.odbc.retstr[field], size + 1); if (Config->conn.odbc.retstr[field] == NULL) { SMSD_Log(DEBUG_ERROR, Config, "Field %d returning NULL, failed to allocate %d bytes of memory", field, size + 1); return NULL; } /* Actually grab result from database */ ret = SQLGetData(res->odbc, field + 1, SQL_C_CHAR, Config->conn.odbc.retstr[field], size + 1, &sqllen); if (!SQL_SUCCEEDED(ret)) { SMSDODBC_LogError(Config, ret, SQL_HANDLE_STMT, res->odbc, "SQLGetData(string) failed"); return NULL; } SMSD_Log(DEBUG_SQL, Config, "Field %d returning string \"%s\"", field, Config->conn.odbc.retstr[field]); return Config->conn.odbc.retstr[field]; }
/* Connects to database */ static GSM_Error SMSDODBC_Connect(GSM_SMSDConfig * Config) { SQLRETURN ret; int field; char driver_name[1000]; SQLSMALLINT len; for (field = 0; field < SMSD_ODBC_MAX_RETURN_STRINGS; field++) { Config->conn.odbc.retstr[field] = NULL; } ret = SQLAllocHandle (SQL_HANDLE_ENV, SQL_NULL_HANDLE, &Config->conn.odbc.env); if (!SQL_SUCCEEDED(ret)) { SMSDODBC_LogError(Config, ret, SQL_HANDLE_ENV, Config->conn.odbc.env, "SQLAllocHandle(ENV) failed"); return ERR_DB_DRIVER; } ret = SQLSetEnvAttr (Config->conn.odbc.env, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0); if (!SQL_SUCCEEDED(ret)) { SMSDODBC_LogError(Config, ret, SQL_HANDLE_ENV, Config->conn.odbc.env, "SQLSetEnvAttr failed"); return ERR_DB_CONFIG; } ret = SQLAllocHandle (SQL_HANDLE_DBC, Config->conn.odbc.env, &Config->conn.odbc.dbc); if (!SQL_SUCCEEDED(ret)) { SMSDODBC_LogError(Config, ret, SQL_HANDLE_ENV, Config->conn.odbc.env, "SQLAllocHandle(DBC) failed"); return ERR_DB_CONFIG; } 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, ret, SQL_HANDLE_DBC, Config->conn.odbc.dbc, "SQLConnect failed"); return ERR_DB_CONNECT; } ret = SQLGetInfo(Config->conn.odbc.dbc, SQL_DRIVER_NAME, driver_name, sizeof(driver_name), &len); if (!SQL_SUCCEEDED(ret)) { SMSDODBC_LogError(Config, ret, SQL_HANDLE_DBC, Config->conn.odbc.dbc, "SQLGetInfo failed"); return ERR_DB_CONNECT; } else{ SMSD_Log(DEBUG_NOTICE, Config, "Connected to driver %s", driver_name); } return ERR_NONE; }
const char *SMSDODBC_GetString(GSM_SMSDConfig * Config, SQL_result *res, unsigned int field) { SQLLEN size; SQLRETURN ret; char shortbuffer[1]; if (field > SMSD_ODBC_MAX_RETURN_STRINGS) { SMSD_Log(DEBUG_ERROR, Config, "Field %d returning NULL, too many fields!", field); return NULL; } /* Figure out string length */ ret = SQLGetData(res->odbc, field + 1, SQL_C_CHAR, shortbuffer, 0, &size); if (!SQL_SUCCEEDED(ret)) { SMSDODBC_LogError(Config, ret, SQL_HANDLE_STMT, res->odbc, "SQLGetData(string,0) failed"); return NULL; } /* Did not we get NULL? */ if (size == SQL_NULL_DATA) { SMSD_Log(DEBUG_SQL, Config, "Field %d returning NULL", field); return NULL; } /* Allocate string */ Config->conn.odbc.retstr[field] = realloc(Config->conn.odbc.retstr[field], size + 1); if (Config->conn.odbc.retstr[field] == NULL) { SMSD_Log(DEBUG_ERROR, Config, "Field %d returning NULL, failed to allocate %ld bytes of memory", field, (long)(size + 1)); return NULL; } /* Actually grab result from database */ ret = SQLGetData(res->odbc, field + 1, SQL_C_CHAR, Config->conn.odbc.retstr[field], size + 1, &size); if (!SQL_SUCCEEDED(ret)) { SMSDODBC_LogError(Config, ret, SQL_HANDLE_STMT, res->odbc, "SQLGetData(string) failed"); return NULL; } SMSD_Log(DEBUG_SQL, Config, "Field %d returning string \"%s\"", field, Config->conn.odbc.retstr[field]); return Config->conn.odbc.retstr[field]; }
long long SMSDODBC_GetNumber(GSM_SMSDConfig * Config, SQL_result *res, unsigned int field) { SQLRETURN ret; SQLINTEGER value = -1; ret = SQLGetData(res->odbc, field + 1, SQL_C_SLONG, &value, 0, NULL); if (!SQL_SUCCEEDED(ret)) { SMSDODBC_LogError(Config, ret, SQL_HANDLE_STMT, res->odbc, "SQLGetData(long) failed"); return -1; } return value; }
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, ret, SQL_HANDLE_DBC, Config->conn.odbc.dbc, "SQLRowCount failed"); return 0; } return (unsigned long)count; }
/* set pointer to next row */ int SMSDODBC_NextRow(GSM_SMSDConfig * Config, SQL_result *res) { SQLRETURN ret; ret = SQLFetch(res->odbc); if (!SQL_SUCCEEDED(ret)) { if (ret != SQL_NO_DATA) { SMSDODBC_LogError(Config, ret, SQL_HANDLE_STMT, res->odbc, "SQLFetch failed"); } return 0; } return 1; }
time_t SMSDODBC_GetDate(GSM_SMSDConfig * Config, SQL_result *res, unsigned int field) { SQL_TIMESTAMP_STRUCT sqltime; GSM_DateTime DT; SQLRETURN ret; ret = SQLGetData(res->odbc, field + 1, SQL_C_TYPE_TIMESTAMP, &sqltime, 0, NULL); if (!SQL_SUCCEEDED(ret)) { SMSDODBC_LogError(Config, ret, SQL_HANDLE_STMT, res->odbc, "SQLGetData(timestamp) failed"); return -1; } DT.Year = sqltime.year; DT.Month = sqltime.month; DT.Day = sqltime.day; DT.Hour = sqltime.hour; DT.Minute = sqltime.minute; DT.Second = sqltime.second; return Fill_Time_T(DT); }
static GSM_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 ERR_SQL; } ret = SQLExecDirect (res->odbc, (SQLCHAR*)query, SQL_NTS); /* * If SQLExecDirect executes a searched update, insert, or delete * statement that does not affect any rows at the data source, the call * to SQLExecDirect returns SQL_NO_DATA. */ if (SQL_SUCCEEDED(ret) || ret == SQL_NO_DATA) { return ERR_NONE; } SMSDODBC_LogError(Config, ret, SQL_HANDLE_STMT, res->odbc, "SQLExecDirect failed"); return ERR_SQL; }