1 /*
2 * Copyright (C) 2001-2003 FhG Fokus
3 * Copyright (C) 2007-2008 1&1 Internet AG
4 *
5 * This file is part of Kamailio, a free SIP server.
6 *
7 * Kamailio is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version
11 *
12 * Kamailio is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 /**
23 * \file lib/srdb1/db_res.c
24 * \brief Functions to manage result structures
25 * \ingroup db1
26 *
27 * Provides some convenience macros and some memory management
28 * functions for result structures.
29 */
30
31 #include "db_res.h"
32
33 #include "db_row.h"
34 #include "../../core/dprint.h"
35 #include "../../core/mem/mem.h"
36
37 #include <string.h>
38
39 /*
40 * Release memory used by rows
41 */
db_free_rows(db1_res_t * _r)42 int db_free_rows(db1_res_t* _r)
43 {
44 int i;
45
46 if (!_r) {
47 LM_ERR("invalid parameter value\n");
48 return -1;
49 }
50
51 if(RES_ROWS(_r)){
52 LM_DBG("freeing %d rows\n", RES_ROW_N(_r));
53 for(i = 0; i < RES_ROW_N(_r); i++) {
54 db_free_row(&(RES_ROWS(_r)[i]));
55 }
56 }
57 RES_ROW_N(_r) = 0;
58
59 if (RES_ROWS(_r)) {
60 LM_DBG("freeing rows at %p\n", RES_ROWS(_r));
61 pkg_free(RES_ROWS(_r));
62 RES_ROWS(_r) = NULL;
63 }
64 return 0;
65 }
66
67
68 /*
69 * Release memory used by columns
70 */
db_free_columns(db1_res_t * _r)71 int db_free_columns(db1_res_t* _r)
72 {
73 int col;
74
75 if (!_r) {
76 LM_ERR("invalid parameter value\n");
77 return -1;
78 }
79 LM_DBG("freeing %d columns\n", RES_COL_N(_r));
80 /* free memory previously allocated to save column names */
81 for(col = 0; col < RES_COL_N(_r); col++) {
82 if (RES_NAMES(_r)[col]!=NULL) {
83 LM_DBG("freeing RES_NAMES[%d] at %p\n", col, RES_NAMES(_r)[col]);
84 /* free column name if it was allocated */
85 if ((RES_COL_FLAGS(_r) & DB1_FCOL_FREE) && RES_NAMES(_r)[col]->s != NULL) {
86 pkg_free(RES_NAMES(_r)[col]->s);
87 }
88 pkg_free((str *)RES_NAMES(_r)[col]);
89 RES_NAMES(_r)[col] = NULL;
90 }
91 }
92 RES_COL_N(_r) = 0;
93
94 /* free names and types */
95 if (RES_NAMES(_r)) {
96 LM_DBG("freeing result names at %p\n", RES_NAMES(_r));
97 pkg_free(RES_NAMES(_r));
98 RES_NAMES(_r) = NULL;
99 }
100 if (RES_TYPES(_r)) {
101 LM_DBG("freeing result types at %p\n", RES_TYPES(_r));
102 pkg_free(RES_TYPES(_r));
103 RES_TYPES(_r) = NULL;
104 }
105 return 0;
106 }
107
108 /*
109 * Create a new result structure and initialize it
110 */
db_new_result(void)111 db1_res_t* db_new_result(void)
112 {
113 db1_res_t* r = NULL;
114 r = (db1_res_t*)pkg_malloc(sizeof(db1_res_t));
115 if (!r) {
116 PKG_MEM_ERROR;
117 return 0;
118 }
119 LM_DBG("allocate %d bytes for result set at %p\n",
120 (int)sizeof(db1_res_t), r);
121 memset(r, 0, sizeof(db1_res_t));
122 return r;
123 }
124
125 /*
126 * Release memory used by a result structure
127 */
db_free_result(db1_res_t * _r)128 int db_free_result(db1_res_t* _r)
129 {
130 if (!_r)
131 {
132 LM_ERR("invalid parameter\n");
133 return -1;
134 }
135
136 db_free_columns(_r);
137 db_free_rows(_r);
138 LM_DBG("freeing result set at %p\n", _r);
139 pkg_free(_r);
140 _r = NULL;
141 return 0;
142 }
143
144 /*
145 * Allocate storage for column names and type in existing
146 * result structure.
147 */
db_allocate_columns(db1_res_t * _r,const unsigned int cols)148 int db_allocate_columns(db1_res_t* _r, const unsigned int cols)
149 {
150 RES_NAMES(_r) = (db_key_t*)pkg_malloc(sizeof(db_key_t) * cols);
151 if (!RES_NAMES(_r)) {
152 PKG_MEM_ERROR;
153 return -1;
154 }
155 memset(RES_NAMES(_r), 0, sizeof(db_key_t) * cols);
156 LM_DBG("allocate %d bytes for result names at %p\n",
157 (int)(sizeof(db_key_t) * cols),
158 RES_NAMES(_r));
159
160 RES_TYPES(_r) = (db_type_t*)pkg_malloc(sizeof(db_type_t) * cols);
161 if (!RES_TYPES(_r)) {
162 PKG_MEM_ERROR;
163 pkg_free(RES_NAMES(_r));
164 return -1;
165 }
166 memset(RES_TYPES(_r), 0, sizeof(db_type_t) * cols);
167 LM_DBG("allocate %d bytes for result types at %p\n",
168 (int)(sizeof(db_type_t) * cols),
169 RES_TYPES(_r));
170
171 return 0;
172 }
173
174
175 /**
176 * Allocate memory for rows.
177 * \param _res result set
178 * \return zero on success, negative on errors
179 */
db_allocate_rows(db1_res_t * _res)180 int db_allocate_rows(db1_res_t* _res)
181 {
182 int len = sizeof(db_row_t) * RES_ROW_N(_res);
183 RES_ROWS(_res) = (struct db_row*)pkg_malloc(len);
184 if (!RES_ROWS(_res)) {
185 PKG_MEM_ERROR;
186 return -1;
187 }
188 LM_DBG("allocate %d bytes for rows at %p\n", len, RES_ROWS(_res));
189 memset(RES_ROWS(_res), 0, len);
190
191 return 0;
192 }
193
194 /**
195 * Reallocate memory for rows.
196 * \param _res result set
197 * \param _nsize new number of rows in result set
198 * \return zero on success, negative on errors
199 */
db_reallocate_rows(db1_res_t * _res,int _nsize)200 int db_reallocate_rows(db1_res_t* _res, int _nsize)
201 {
202 int len;
203 int osize;
204 db_row_t *orows;
205
206 orows = RES_ROWS(_res);
207 osize = RES_ROW_N(_res);
208
209 RES_ROW_N(_res) = _nsize;
210 len = sizeof(db_row_t) * RES_ROW_N(_res);
211 RES_ROWS(_res) = (struct db_row*)pkg_malloc(len);
212 if (!RES_ROWS(_res)) {
213 PKG_MEM_ERROR;
214 return -1;
215 }
216 LM_DBG("allocate %d bytes for rows at %p\n", len, RES_ROWS(_res));
217 memset(RES_ROWS(_res), 0, len);
218
219 if(orows==NULL)
220 return 0;
221 memcpy(RES_ROWS(_res), orows,
222 ((osize<_nsize)?osize:_nsize)*sizeof(db_row_t));
223 pkg_free(orows);
224 return 0;
225 }
226