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 #include "../../mem/mem.h"
00034 #include "../../dprint.h"
00035 #include "row.h"
00036 #include "../../db/db_res.h"
00037 #include "con.h"
00038 #include "res.h"
00039 #include "list.h"
00040 #include <stdlib.h>
00041 #include <string.h>
00042
00043
00044
00045
00046 int db_unixodbc_get_columns(const db_con_t* _h, db_res_t* _r)
00047 {
00048 int col;
00049 SQLSMALLINT cols;
00050
00051 if ((!_h) || (!_r)) {
00052 LM_ERR("invalid parameter\n");
00053 return -1;
00054 }
00055
00056
00057 SQLNumResultCols(CON_RESULT(_h), &cols);
00058 RES_COL_N(_r) = cols;
00059 if (!RES_COL_N(_r)) {
00060 LM_ERR("no columns returned from the query\n");
00061 return -2;
00062 } else {
00063 LM_DBG("%d columns returned from the query\n", RES_COL_N(_r));
00064 }
00065
00066 if (db_allocate_columns(_r, RES_COL_N(_r)) != 0) {
00067 LM_ERR("could not allocate columns\n");
00068 return -3;
00069 }
00070
00071 for(col = 0; col < RES_COL_N(_r); col++)
00072 {
00073 RES_NAMES(_r)[col] = (str*)pkg_malloc(sizeof(str));
00074 if (! RES_NAMES(_r)[col]) {
00075 LM_ERR("no private memory left\n");
00076 db_free_columns(_r);
00077 return -4;
00078 }
00079 LM_DBG("allocate %lu bytes for RES_NAMES[%d] at %p\n",
00080 (unsigned long)sizeof(str),col, RES_NAMES(_r)[col]);
00081
00082 char columnname[80];
00083 SQLRETURN ret;
00084 SQLSMALLINT namelength, datatype, decimaldigits, nullable;
00085 SQLULEN columnsize;
00086
00087 ret = SQLDescribeCol(CON_RESULT(_h), col + 1, (SQLCHAR *)columnname, 80,
00088 &namelength, &datatype, &columnsize, &decimaldigits, &nullable);
00089 if(!SQL_SUCCEEDED(ret)) {
00090 LM_ERR("SQLDescribeCol failed: %d\n", ret);
00091 db_unixodbc_extract_error("SQLExecDirect", CON_RESULT(_h), SQL_HANDLE_STMT,
00092 NULL);
00093
00094 }
00095
00096 RES_NAMES(_r)[col]->s = columnname;
00097 RES_NAMES(_r)[col]->len = namelength;
00098
00099 LM_DBG("RES_NAMES(%p)[%d]=[%.*s]\n", RES_NAMES(_r)[col], col,
00100 RES_NAMES(_r)[col]->len, RES_NAMES(_r)[col]->s);
00101
00102 switch(datatype)
00103 {
00104 case SQL_SMALLINT:
00105 case SQL_INTEGER:
00106 case SQL_TINYINT:
00107 case SQL_DECIMAL:
00108 case SQL_NUMERIC:
00109 LM_DBG("use DB_INT result type\n");
00110 RES_TYPES(_r)[col] = DB_INT;
00111 break;
00112
00113 case SQL_BIGINT:
00114 LM_DBG("use DB_BIGINT result type\n");
00115 RES_TYPES(_r)[col] = DB_BIGINT;
00116 break;
00117
00118 case SQL_REAL:
00119 case SQL_FLOAT:
00120 case SQL_DOUBLE:
00121 LM_DBG("use DB_DOUBLE result type\n");
00122 RES_TYPES(_r)[col] = DB_DOUBLE;
00123 break;
00124
00125 case SQL_TYPE_TIMESTAMP:
00126 case SQL_DATE:
00127 case SQL_TIME:
00128 case SQL_TIMESTAMP:
00129 case SQL_TYPE_DATE:
00130 case SQL_TYPE_TIME:
00131 LM_DBG("use DB_DATETIME result type\n");
00132 RES_TYPES(_r)[col] = DB_DATETIME;
00133 break;
00134
00135 case SQL_CHAR:
00136 case SQL_VARCHAR:
00137 case SQL_WCHAR:
00138 case SQL_WVARCHAR:
00139 LM_DBG("use DB_STRING result type\n");
00140 RES_TYPES(_r)[col] = DB_STRING;
00141 break;
00142
00143 case SQL_BINARY:
00144 case SQL_VARBINARY:
00145 case SQL_LONGVARBINARY:
00146 case SQL_BIT:
00147 case SQL_LONGVARCHAR:
00148 case SQL_WLONGVARCHAR:
00149 LM_DBG("use DB_BLOB result type\n");
00150 RES_TYPES(_r)[col] = DB_BLOB;
00151 break;
00152
00153 default:
00154 LM_WARN("unhandled data type column (%.*s) type id (%d), "
00155 "use DB_STRING as default\n", RES_NAMES(_r)[col]->len,
00156 RES_NAMES(_r)[col]->s, datatype);
00157 RES_TYPES(_r)[col] = DB_STRING;
00158 break;
00159 }
00160 }
00161 return 0;
00162 }
00163
00164
00165
00166
00167 static inline int db_unixodbc_convert_rows(const db_con_t* _h, db_res_t* _r)
00168 {
00169 int i = 0, ret = 0;
00170 SQLSMALLINT columns;
00171 list* rows = NULL;
00172 list* rowstart = NULL;
00173 strn* temp_row = NULL;
00174
00175 if((!_h) || (!_r)) {
00176 LM_ERR("invalid parameter\n");
00177 return -1;
00178 }
00179
00180 SQLNumResultCols(CON_RESULT(_h), (SQLSMALLINT *)&columns);
00181 temp_row = (strn*)pkg_malloc( columns*sizeof(strn) );
00182 if(!temp_row) {
00183 LM_ERR("no private memory left\n");
00184 return -1;
00185 }
00186
00187 while(SQL_SUCCEEDED(ret = SQLFetch(CON_RESULT(_h))))
00188 {
00189 for(i=0; i < columns; i++)
00190 {
00191 SQLLEN indicator;
00192 ret = SQLGetData(CON_RESULT(_h), i+1, SQL_C_CHAR,
00193 temp_row[i].s, STRN_LEN, &indicator);
00194 if (SQL_SUCCEEDED(ret)) {
00195 if (indicator == SQL_NULL_DATA)
00196 strcpy(temp_row[i].s, "NULL");
00197 }
00198 else {
00199 LM_ERR("SQLGetData failed\n");
00200 }
00201 }
00202
00203 if (db_unixodbc_list_insert(&rowstart, &rows, columns, temp_row) < 0) {
00204 LM_ERR("insert failed\n");
00205 pkg_free(temp_row);
00206 temp_row= NULL;
00207 return -5;
00208 }
00209 RES_ROW_N(_r)++;
00210 }
00211
00212 pkg_free(temp_row);
00213 CON_ROW(_h) = NULL;
00214
00215 if (!RES_ROW_N(_r)) {
00216 RES_ROWS(_r) = 0;
00217 return 0;
00218 }
00219
00220 if (db_allocate_rows(_r) != 0) {
00221 LM_ERR("could not allocate rows");
00222 db_unixodbc_list_destroy(rowstart);
00223 return -2;
00224 }
00225
00226 i = 0;
00227 rows = rowstart;
00228 while(rows)
00229 {
00230 CON_ROW(_h) = rows->data;
00231 if (!CON_ROW(_h))
00232 {
00233 LM_ERR("string null\n");
00234 RES_ROW_N(_r) = i;
00235 db_free_rows(_r);
00236 db_unixodbc_list_destroy(rowstart);
00237 return -3;
00238 }
00239 if (db_unixodbc_convert_row(_h, _r, &(RES_ROWS(_r)[i]), rows->lengths) < 0) {
00240 LM_ERR("converting row failed #%d\n", i);
00241 RES_ROW_N(_r) = i;
00242 db_free_rows(_r);
00243 db_unixodbc_list_destroy(rowstart);
00244 return -4;
00245 }
00246 i++;
00247 rows = rows->next;
00248 }
00249 db_unixodbc_list_destroy(rowstart);
00250 return 0;
00251 }
00252
00253
00254
00255
00256
00257 int db_unixodbc_convert_result(const db_con_t* _h, db_res_t* _r)
00258 {
00259 if (!_h || !_r) {
00260 LM_ERR("invalid parameter\n");
00261 return -1;
00262 }
00263
00264 if (db_unixodbc_get_columns(_h, _r) < 0) {
00265 LM_ERR("getting column names failed\n");
00266 return -2;
00267 }
00268
00269 if (db_unixodbc_convert_rows(_h, _r) < 0) {
00270 LM_ERR("converting rows failed\n");
00271 db_free_columns(_r);
00272 return -3;
00273 }
00274 return 0;
00275 }