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
00035
00036
00043 #include <stdlib.h>
00044 #include <string.h>
00045 #include "../../lib/srdb1/db_id.h"
00046 #include "../../lib/srdb1/db_res.h"
00047 #include "../../lib/srdb1/db_con.h"
00048 #include "../../dprint.h"
00049 #include "../../mem/mem.h"
00050 #include "km_res.h"
00051 #include "km_val.h"
00052 #include "km_pg_con.h"
00053 #include "km_pg_type.h"
00054
00055
00062 int db_postgres_convert_result(const db1_con_t* _h, db1_res_t* _r)
00063 {
00064 if (!_h || !_r) {
00065 LM_ERR("invalid parameter value\n");
00066 return -1;
00067 }
00068
00069 if (db_postgres_get_columns(_h, _r) < 0) {
00070 LM_ERR("failed to get column names\n");
00071 return -2;
00072 }
00073
00074 if (db_postgres_convert_rows(_h, _r) < 0) {
00075 LM_ERR("failed to convert rows\n");
00076 db_free_columns(_r);
00077 return -3;
00078 }
00079 return 0;
00080 }
00081
00082
00089 int db_postgres_get_columns(const db1_con_t* _h, db1_res_t* _r)
00090 {
00091 int col, datatype;
00092
00093 if (!_h || !_r) {
00094 LM_ERR("invalid parameter value\n");
00095 return -1;
00096 }
00097
00098
00099 RES_ROW_N(_r) = PQntuples(CON_RESULT(_h));
00100
00101
00102 RES_COL_N(_r) = PQnfields(CON_RESULT(_h));
00103
00104 if (!RES_COL_N(_r)) {
00105 LM_DBG("no columns returned from the query\n");
00106 return -2;
00107 } else {
00108 LM_DBG("%d columns returned from the query\n", RES_COL_N(_r));
00109 }
00110
00111 if (db_allocate_columns(_r, RES_COL_N(_r)) != 0) {
00112 LM_ERR("could not allocate columns\n");
00113 return -3;
00114 }
00115
00116
00117 for(col = 0; col < RES_COL_N(_r); col++) {
00118
00119 RES_NAMES(_r)[col] = (str*)pkg_malloc(sizeof(str));
00120 if (! RES_NAMES(_r)[col]) {
00121 LM_ERR("no private memory left\n");
00122 db_free_columns(_r);
00123 return -4;
00124 }
00125 LM_DBG("allocate %d bytes for RES_NAMES[%d] at %p\n", (unsigned int) sizeof(str), col,
00126 RES_NAMES(_r)[col]);
00127
00128
00129 RES_NAMES(_r)[col]->s = PQfname(CON_RESULT(_h), col);
00130 RES_NAMES(_r)[col]->len = strlen(PQfname(CON_RESULT(_h), col));
00131
00132 LM_DBG("RES_NAMES(%p)[%d]=[%.*s]\n", RES_NAMES(_r)[col], col,
00133 RES_NAMES(_r)[col]->len, RES_NAMES(_r)[col]->s);
00134
00135
00136 switch(datatype = PQftype(CON_RESULT(_h),col))
00137 {
00138 case INT2OID:
00139 case INT4OID:
00140 LM_DBG("use DB1_INT result type\n");
00141 RES_TYPES(_r)[col] = DB1_INT;
00142 break;
00143
00144 case INT8OID:
00145 LM_DBG("use DB1_BIGINT result type\n");
00146 RES_TYPES(_r)[col] = DB1_BIGINT;
00147
00148 case FLOAT4OID:
00149 case FLOAT8OID:
00150 case NUMERICOID:
00151 LM_DBG("use DB1_DOUBLE result type\n");
00152 RES_TYPES(_r)[col] = DB1_DOUBLE;
00153 break;
00154
00155 case DATEOID:
00156 case TIMESTAMPOID:
00157 case TIMESTAMPTZOID:
00158 LM_DBG("use DB1_DATETIME result type\n");
00159 RES_TYPES(_r)[col] = DB1_DATETIME;
00160 break;
00161
00162 case BOOLOID:
00163 case CHAROID:
00164 case VARCHAROID:
00165 case BPCHAROID:
00166 LM_DBG("use DB1_STRING result type\n");
00167 RES_TYPES(_r)[col] = DB1_STRING;
00168 break;
00169
00170 case TEXTOID:
00171 case BYTEAOID:
00172 LM_DBG("use DB1_BLOB result type\n");
00173 RES_TYPES(_r)[col] = DB1_BLOB;
00174 break;
00175
00176 case BITOID:
00177 case VARBITOID:
00178 LM_DBG("use DB1_BITMAP result type\n");
00179 RES_TYPES(_r)[col] = DB1_BITMAP;
00180 break;
00181
00182 default:
00183 LM_WARN("unhandled data type column (%.*s) type id (%d), "
00184 "use DB1_STRING as default\n", RES_NAMES(_r)[col]->len,
00185 RES_NAMES(_r)[col]->s, datatype);
00186 RES_TYPES(_r)[col] = DB1_STRING;
00187 break;
00188 }
00189 }
00190 return 0;
00191 }
00192
00193
00200 int db_postgres_convert_rows(const db1_con_t* _h, db1_res_t* _r)
00201 {
00202 char **row_buf, *s;
00203 int row, col, len;
00204
00205 if (!_h || !_r) {
00206 LM_ERR("invalid parameter\n");
00207 return -1;
00208 }
00209
00210 if (!RES_ROW_N(_r)) {
00211 LM_DBG("no rows returned from the query\n");
00212 RES_ROWS(_r) = 0;
00213 return 0;
00214 }
00215
00216 len = sizeof(char *) * RES_COL_N(_r);
00217 row_buf = (char**)pkg_malloc(len);
00218 if (!row_buf) {
00219 LM_ERR("no private memory left\n");
00220 return -1;
00221 }
00222 LM_DBG("allocate for %d columns %d bytes in row buffer at %p\n", RES_COL_N(_r), len, row_buf);
00223
00224 if (db_allocate_rows(_r) < 0) {
00225 LM_ERR("could not allocate rows\n");
00226 LM_DBG("freeing row buffer at %p\n", row_buf);
00227 pkg_free(row_buf);
00228 return -2;
00229 }
00230
00231 for(row = RES_LAST_ROW(_r); row < (RES_LAST_ROW(_r) + RES_ROW_N(_r)); row++) {
00232
00233 memset(row_buf, 0, len);
00234 for(col = 0; col < RES_COL_N(_r); col++) {
00235
00236
00237
00238
00239
00240
00241
00242 s = PQgetvalue(CON_RESULT(_h), row, col);
00243 LM_DBG("PQgetvalue(%p,%d,%d)=[%s]\n", _h, row, col, s);
00244
00245
00246
00247
00248
00249 if (PQgetisnull(CON_RESULT(_h), row, col) == 0) {
00250 row_buf[col] = s;
00251 LM_DBG("[%d][%d] Column[%.*s]=[%s]\n",
00252 row, col, RES_NAMES(_r)[col]->len, RES_NAMES(_r)[col]->s, row_buf[col]);
00253 }
00254 }
00255
00256
00257 if(db_postgres_convert_row(_h, _r, &(RES_ROWS(_r)[row - RES_LAST_ROW(_r)]), row_buf)<0){
00258 LM_ERR("failed to convert row #%d\n", row);
00259 RES_ROW_N(_r) = row - RES_LAST_ROW(_r);
00260 LM_DBG("freeing row buffer at %p\n", row_buf);
00261 pkg_free(row_buf);
00262 db_free_rows(_r);
00263 return -4;
00264 }
00265 }
00266
00267 LM_DBG("freeing row buffer at %p\n", row_buf);
00268 pkg_free(row_buf);
00269 row_buf = NULL;
00270 return 0;
00271 }
00272
00273
00282 int db_postgres_convert_row(const db1_con_t* _h, db1_res_t* _r, db_row_t* _row,
00283 char **row_buf)
00284 {
00285 int col, col_len;
00286
00287 if (!_h || !_r || !_row) {
00288 LM_ERR("invalid parameter value\n");
00289 return -1;
00290 }
00291
00292 if (db_allocate_row(_r, _row) != 0) {
00293 LM_ERR("could not allocate row\n");
00294 return -2;
00295 }
00296
00297
00298 for(col = 0; col < ROW_N(_row); col++) {
00299
00300 if (!row_buf[col]) {
00301 col_len = 0;
00302 } else {
00303 col_len = strlen(row_buf[col]);
00304 }
00305
00306 if (db_postgres_str2val(RES_TYPES(_r)[col], &(ROW_VALUES(_row)[col]),
00307 row_buf[col], col_len) < 0) {
00308 LM_ERR("failed to convert value\n");
00309 LM_DBG("free row at %p\n", _row);
00310 db_free_row(_row);
00311 return -3;
00312 }
00313 }
00314 return 0;
00315 }