db_mysql/res.c

Go to the documentation of this file.
00001 /* 
00002  * $Id: res.c 5362 2008-12-15 16:33:22Z henningw $ 
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 
00027 /*! \file
00028  *  \brief DB_MYSQL :: Result related functions
00029  *  \ingroup db_mysql
00030  *  Module: \ref db_mysql
00031  */
00032 
00033 
00034 #include <string.h>
00035 #include <mysql/mysql.h>
00036 #include "../../db/db_res.h"
00037 #include "../../mem/mem.h"
00038 #include "../../dprint.h"
00039 #include "row.h"
00040 #include "my_con.h"
00041 #include "res.h"
00042 
00043 
00044 /*!
00045  * \brief Get and convert columns from a result
00046  *
00047  * Get and convert columns from a result, fills the result structure
00048  * with data from the database.
00049  * \param _h database connection
00050  * \param _r database result set
00051  * \return 0 on success, negative on failure
00052  */
00053 int db_mysql_get_columns(const db_con_t* _h, db_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 DB_INT result type\n");
00101             RES_TYPES(_r)[col] = DB_INT;
00102             break;
00103 
00104          case MYSQL_TYPE_LONGLONG:
00105             LM_DBG("use DB_BIGINT result type\n");
00106             RES_TYPES(_r)[col] = DB_BIGINT;
00107             break;
00108 
00109          case MYSQL_TYPE_FLOAT:
00110          case MYSQL_TYPE_DOUBLE:
00111             LM_DBG("use DB_DOUBLE result type\n");
00112             RES_TYPES(_r)[col] = DB_DOUBLE;
00113             break;
00114 
00115          case MYSQL_TYPE_DATETIME:
00116             LM_DBG("use DB_DATETIME result type\n");
00117             RES_TYPES(_r)[col] = DB_DATETIME;
00118             break;
00119 
00120          case MYSQL_TYPE_BLOB:
00121             LM_DBG("use DB_BLOB result type\n");
00122             RES_TYPES(_r)[col] = DB_BLOB;
00123             break;
00124 
00125          case FIELD_TYPE_SET:
00126             LM_DBG("use DB_BITMAP result type\n");
00127             RES_TYPES(_r)[col] = DB_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 DB_STRING result type\n");
00137             RES_TYPES(_r)[col] = DB_STRING;
00138             break;
00139 
00140          default:
00141             LM_WARN("unhandled data type column (%.*s) type id (%d), "
00142                   "use DB_STRING as default\n", RES_NAMES(_r)[col]->len,
00143                   RES_NAMES(_r)[col]->s, fields[col].type);
00144             RES_TYPES(_r)[col] = DB_STRING;
00145             break;
00146       }
00147    }
00148    return 0;
00149 }
00150 
00151 
00152 /*!
00153  * \brief Convert rows from mysql to db API representation
00154  * \param _h database connection
00155  * \param _r database result set
00156  * \return 0 on success, negative on failure
00157  */
00158 static inline int db_mysql_convert_rows(const db_con_t* _h, db_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 
00198 /*!
00199  * \brief Fill the result structure with data from database
00200  * \param _h database connection
00201  * \param _r database result
00202  * \return 0 on success, negative on failure
00203  */
00204 int db_mysql_convert_result(const db_con_t* _h, db_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 

Generated on Mon May 21 18:00:31 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6