00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include "con.h"
00035 #include "../../mem/mem.h"
00036 #include "../../dprint.h"
00037 #include "../../ut.h"
00038 #include <time.h>
00039
00040 #define DSN_ATTR "DSN="
00041 #define DSN_ATTR_LEN (sizeof(DSN_ATTR)-1)
00042 #define UID_ATTR "UID="
00043 #define UID_ATTR_LEN (sizeof(UID_ATTR)-1)
00044 #define PWD_ATTR "PWD="
00045 #define PWD_ATTR_LEN (sizeof(PWD_ATTR)-1)
00046
00047
00048 char *db_unixodbc_build_conn_str(const struct db_id* id, char *buf)
00049 {
00050 int len, ld, lu, lp;
00051 char *p;
00052
00053 if (!buf) return 0;
00054
00055 ld = id->database?strlen(id->database):0;
00056 lu = id->username?strlen(id->username):0;
00057 lp = id->password?strlen(id->password):0;
00058
00059 len = (ld?(DSN_ATTR_LEN + ld + 1):0)
00060 + (lu?(UID_ATTR_LEN + lu + 1):0)
00061 + PWD_ATTR_LEN + lp + 1;
00062
00063 if ( len>=MAX_CONN_STR_LEN ){
00064 LM_ERR("connection string too long! Increase MAX_CONN_STR_LEN"
00065 " and recompile\n");
00066 return 0;
00067 }
00068
00069 p = buf;
00070 if (ld) {
00071 memcpy( p , DSN_ATTR, DSN_ATTR_LEN);
00072 p += DSN_ATTR_LEN;
00073 memcpy( p, id->database, ld);
00074 p += ld;
00075 }
00076 if (lu) {
00077 *(p++) = ';';
00078 memcpy( p , UID_ATTR, UID_ATTR_LEN);
00079 p += UID_ATTR_LEN;
00080 memcpy( p, id->username, lu);
00081 p += lu;
00082 }
00083 if (lp) {
00084 *(p++) = ';';
00085 memcpy( p , PWD_ATTR, PWD_ATTR_LEN);
00086 p += PWD_ATTR_LEN;
00087 memcpy( p, id->password, lp);
00088 p += lp;
00089 }
00090 *(p++) = ';';
00091 *p = 0 ;
00092
00093 return buf;
00094 }
00095
00096
00097
00098
00099
00100
00101 struct my_con* db_unixodbc_new_connection(struct db_id* id)
00102 {
00103 SQLCHAR outstr[1024];
00104 SQLSMALLINT outstrlen;
00105 int ret;
00106 struct my_con* ptr;
00107 char conn_str[MAX_CONN_STR_LEN];
00108
00109 if (!id)
00110 {
00111 LM_ERR("invalid parameter value\n");
00112 return 0;
00113 }
00114
00115 ptr = (struct my_con*)pkg_malloc(sizeof(struct my_con));
00116 if (!ptr)
00117 {
00118 LM_ERR("no more memory left\n");
00119 return 0;
00120 }
00121
00122 memset(ptr, 0, sizeof(struct my_con));
00123 ptr->ref = 1;
00124
00125 ret = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &(ptr->env));
00126 if ((ret != SQL_SUCCESS) && (ret != SQL_SUCCESS_WITH_INFO))
00127 {
00128 LM_ERR("could not alloc a SQL handle\n");
00129 if (ptr) pkg_free(ptr);
00130 return 0;
00131 }
00132
00133 ret = SQLSetEnvAttr(ptr->env, SQL_ATTR_ODBC_VERSION, (void *) SQL_OV_ODBC3, 0);
00134 if ((ret != SQL_SUCCESS) && (ret != SQL_SUCCESS_WITH_INFO))
00135 {
00136 LM_ERR("could not set the environment\n");
00137 goto err1;
00138 }
00139
00140 ret = SQLAllocHandle(SQL_HANDLE_DBC, ptr->env, &(ptr->dbc));
00141 if ((ret != SQL_SUCCESS) && (ret != SQL_SUCCESS_WITH_INFO))
00142 {
00143 LM_ERR("could not alloc a connection handle %d\n", ret);
00144 goto err1;
00145 }
00146
00147 if (!db_unixodbc_build_conn_str(id, conn_str)) {
00148 LM_ERR("failed to build connection string\n");
00149 goto err2;
00150 }
00151
00152 LM_DBG("opening connection: unixodbc://xxxx:xxxx@%s/%s\n", ZSW(id->host),
00153 ZSW(id->database));
00154
00155 ret = SQLDriverConnect(ptr->dbc, NULL, (SQLCHAR*)conn_str, SQL_NTS,
00156 outstr, sizeof(outstr), &outstrlen,
00157 SQL_DRIVER_COMPLETE);
00158 if (SQL_SUCCEEDED(ret))
00159 {
00160 LM_DBG("connection succeeded with reply <%s>\n", outstr);
00161 if (ret == SQL_SUCCESS_WITH_INFO)
00162 {
00163 LM_DBG("driver reported the following diagnostics\n");
00164 db_unixodbc_extract_error("SQLDriverConnect", ptr->dbc, SQL_HANDLE_DBC, NULL);
00165 }
00166 }
00167 else
00168 {
00169 LM_ERR("failed to connect\n");
00170 db_unixodbc_extract_error("SQLDriverConnect", ptr->dbc, SQL_HANDLE_DBC, NULL);
00171 goto err2;
00172 }
00173
00174 ptr->stmt_handle = NULL;
00175
00176 ptr->timestamp = time(0);
00177 ptr->id = id;
00178 return ptr;
00179
00180 err1:
00181 SQLFreeHandle(SQL_HANDLE_ENV, &(ptr->env));
00182 if (ptr) pkg_free(ptr);
00183 return 0;
00184
00185 err2:
00186 SQLFreeHandle(SQL_HANDLE_ENV, &(ptr->env));
00187 SQLFreeHandle(SQL_HANDLE_DBC, &(ptr->dbc));
00188 if (ptr) pkg_free(ptr);
00189 return 0;
00190 }
00191
00192
00193
00194
00195 void db_unixodbc_free_connection(struct my_con* con)
00196 {
00197 if (!con) return;
00198 SQLFreeHandle(SQL_HANDLE_ENV, con->env);
00199 SQLDisconnect(con->dbc);
00200 SQLFreeHandle(SQL_HANDLE_DBC, con->dbc);
00201 pkg_free(con);
00202 }
00203
00204
00205 void db_unixodbc_extract_error(const char *fn, const SQLHANDLE handle, const SQLSMALLINT type, char* stret)
00206 {
00207 SQLINTEGER i = 0;
00208 SQLINTEGER native;
00209 SQLCHAR state[ 7 ];
00210 SQLCHAR text[256];
00211 SQLSMALLINT len;
00212 SQLRETURN ret;
00213
00214 do
00215 {
00216 ret = SQLGetDiagRec(type, handle, ++i, state, &native, text,
00217 sizeof(text), &len );
00218 if (SQL_SUCCEEDED(ret)) {
00219 LM_ERR("unixodbc:%s=%s:%ld:%ld:%s\n", fn, state, (long)i,
00220 (long)native, text);
00221 if(stret) strcpy( stret, (char*)state );
00222 }
00223 }
00224 while( ret == SQL_SUCCESS );
00225 }