db_mysql/km_res.c

Go to the documentation of this file.
00001 /* 
00002  * $Id$ 
00003  *
00004  * MySQL module result related functions
00005  *
00006  * Copyright (C) 2001-2003 FhG Fokus
00007  * Copyright (C) 2007-2008 1&1 Internet AG
00008  *
00009  * This file is part of Kamailio, a free SIP server.
00010  *
00011  * Kamailio is free software; you can redistribute it and/or modify
00012  * it under the terms of the GNU General Public License as published by
00013  * the Free Software Foundation; either version 2 of the License, or
00014  * (at your option) any later version
00015  *
00016  * Kamailio is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU General Public License 
00022  * along with this program; if not, write to the Free Software 
00023  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00024  */
00025 
00026 
00034 #include <string.h>
00035 #include <mysql/mysql.h>
00036 #include "../../lib/srdb1/db_res.h"
00037 #include "../../mem/mem.h"
00038 #include "../../dprint.h"
00039 #include "km_row.h"
00040 #include "km_my_con.h"
00041 #include "km_res.h"
00042 
00043 
00053 int db_mysql_get_columns(const db1_con_t* _h, db1_res_t* _r)
00054 {
00055         int col;
00056         MYSQL_FIELD* fields;
00057 
00058         if ((!_h) || (!_r)) {
00059                 LM_ERR("invalid parameter\n");
00060                 return -1;
00061         }
00062 
00063         RES_COL_N(_r) = mysql_field_count(CON_CONNECTION(_h));
00064         if (!RES_COL_N(_r)) {
00065                 LM_ERR("no columns returned from the query\n");
00066                 return -2;
00067         } else {
00068                 LM_DBG("%d columns returned from the query\n", RES_COL_N(_r));
00069         }
00070         
00071         if (db_allocate_columns(_r, RES_COL_N(_r)) != 0) {
00072                 LM_ERR("could not allocate columns\n");
00073                 return -3;
00074         }
00075 
00076         fields = mysql_fetch_fields(CON_RESULT(_h));
00077         for(col = 0; col < RES_COL_N(_r); col++) {
00078                 RES_NAMES(_r)[col] = (str*)pkg_malloc(sizeof(str));
00079                 if (! RES_NAMES(_r)[col]) {
00080                         LM_ERR("no private memory left\n");
00081                         db_free_columns(_r);
00082                         return -4;
00083                 }
00084                 LM_DBG("allocate %lu bytes for RES_NAMES[%d] at %p\n",
00085                                 (unsigned long)sizeof(str), col, RES_NAMES(_r)[col]);
00086 
00087                 /* The pointer that is here returned is part of the result structure. */
00088                 RES_NAMES(_r)[col]->s = fields[col].name;
00089                 RES_NAMES(_r)[col]->len = strlen(fields[col].name);
00090 
00091                 LM_DBG("RES_NAMES(%p)[%d]=[%.*s]\n", RES_NAMES(_r)[col], col,
00092                                 RES_NAMES(_r)[col]->len, RES_NAMES(_r)[col]->s);
00093 
00094                 switch(fields[col].type) {
00095                         case MYSQL_TYPE_TINY:
00096                         case MYSQL_TYPE_SHORT:
00097                         case MYSQL_TYPE_LONG:
00098                         case MYSQL_TYPE_INT24:
00099                         case MYSQL_TYPE_TIMESTAMP:
00100                                 LM_DBG("use DB1_INT result type\n");
00101                                 RES_TYPES(_r)[col] = DB1_INT;
00102                                 break;
00103 
00104                         case MYSQL_TYPE_LONGLONG:
00105                                 LM_DBG("use DB1_BIGINT result type\n");
00106                                 RES_TYPES(_r)[col] = DB1_BIGINT;
00107                                 break;
00108 
00109                         case MYSQL_TYPE_FLOAT:
00110                         case MYSQL_TYPE_DOUBLE:
00111                                 LM_DBG("use DB1_DOUBLE result type\n");
00112                                 RES_TYPES(_r)[col] = DB1_DOUBLE;
00113                                 break;
00114 
00115                         case MYSQL_TYPE_DATETIME:
00116                                 LM_DBG("use DB1_DATETIME result type\n");
00117                                 RES_TYPES(_r)[col] = DB1_DATETIME;
00118                                 break;
00119 
00120                         case MYSQL_TYPE_BLOB:
00121                                 LM_DBG("use DB1_BLOB result type\n");
00122                                 RES_TYPES(_r)[col] = DB1_BLOB;
00123                                 break;
00124 
00125                         case FIELD_TYPE_SET:
00126                                 LM_DBG("use DB1_BITMAP result type\n");
00127                                 RES_TYPES(_r)[col] = DB1_BITMAP;
00128                                 break;
00129 
00130                         case MYSQL_TYPE_DECIMAL:
00131                         #if MYSQL_VERSION_ID > 49999
00132                         case MYSQL_TYPE_NEWDECIMAL:
00133                         #endif
00134                         case MYSQL_TYPE_STRING:
00135                         case MYSQL_TYPE_VAR_STRING:
00136                                 LM_DBG("use DB1_STRING result type\n");
00137                                 RES_TYPES(_r)[col] = DB1_STRING;
00138                                 break;
00139 
00140                         default:
00141                                 LM_WARN("unhandled data type column (%.*s) type id (%d), "
00142                                                 "use DB1_STRING as default\n", RES_NAMES(_r)[col]->len,
00143                                                 RES_NAMES(_r)[col]->s, fields[col].type);
00144                                 RES_TYPES(_r)[col] = DB1_STRING;
00145                                 break;
00146                 }
00147         }
00148         return 0;
00149 }
00150 
00151 
00158 static inline int db_mysql_convert_rows(const db1_con_t* _h, db1_res_t* _r)
00159 {
00160         int row;
00161 
00162         if ((!_h) || (!_r)) {
00163                 LM_ERR("invalid parameter\n");
00164                 return -1;
00165         }
00166 
00167         RES_ROW_N(_r) = mysql_num_rows(CON_RESULT(_h));
00168         if (!RES_ROW_N(_r)) {
00169                 LM_DBG("no rows returned from the query\n");
00170                 RES_ROWS(_r) = 0;
00171                 return 0;
00172         }
00173 
00174         if (db_allocate_rows(_r) < 0) {
00175                 LM_ERR("could not allocate rows");
00176                 return -2;
00177         }
00178 
00179         for(row = 0; row < RES_ROW_N(_r); row++) {
00180                 CON_ROW(_h) = mysql_fetch_row(CON_RESULT(_h));
00181                 if (!CON_ROW(_h)) {
00182                         LM_ERR("driver error: %s\n", mysql_error(CON_CONNECTION(_h)));
00183                         RES_ROW_N(_r) = row;
00184                         db_free_rows(_r);
00185                         return -3;
00186                 }
00187                 if (db_mysql_convert_row(_h, _r, &(RES_ROWS(_r)[row])) < 0) {
00188                         LM_ERR("error while converting row #%d\n", row);
00189                         RES_ROW_N(_r) = row;
00190                         db_free_rows(_r);
00191                         return -4;
00192                 }
00193         }
00194         return 0;
00195 }
00196 
00197 
00204 int db_mysql_convert_result(const db1_con_t* _h, db1_res_t* _r)
00205 {
00206         if ((!_h) || (!_r)) {
00207                 LM_ERR("invalid parameter\n");
00208                 return -1;
00209         }
00210 
00211         if (db_mysql_get_columns(_h, _r) < 0) {
00212                 LM_ERR("error while getting column names\n");
00213                 return -2;
00214         }
00215 
00216         if (db_mysql_convert_rows(_h, _r) < 0) {
00217                 LM_ERR("error while converting rows\n");
00218                 db_free_columns(_r);
00219                 return -3;
00220         }
00221         return 0;
00222 }
00223