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