1 : /*
2 : +----------------------------------------------------------------------+
3 : | PHP Version 6 |
4 : +----------------------------------------------------------------------+
5 : | Copyright (c) 1997-2009 The PHP Group |
6 : +----------------------------------------------------------------------+
7 : | This source file is subject to version 3.01 of the PHP license, |
8 : | that is bundled with this package in the file LICENSE, and is |
9 : | available through the world-wide-web at the following url: |
10 : | http://www.php.net/license/3_01.txt |
11 : | If you did not receive a copy of the PHP license and are unable to |
12 : | obtain it through the world-wide-web, please send a note to |
13 : | license@php.net so we can mail you a copy immediately. |
14 : +----------------------------------------------------------------------+
15 : | Authors: Georg Richter <georg@php.net> |
16 : | Andrey Hristov <andrey@php.net> |
17 : | Ulf Wendel <uw@php.net> |
18 : +----------------------------------------------------------------------+
19 :
20 : $Id: mysqli_warning.c 272367 2008-12-31 11:12:40Z sebastian $
21 : */
22 : #ifdef HAVE_CONFIG_H
23 : #include "config.h"
24 : #endif
25 :
26 : #include <signal.h>
27 :
28 : #include "php.h"
29 : #include "php_ini.h"
30 : #include "ext/standard/info.h"
31 : #include "php_mysqli_structs.h"
32 :
33 :
34 : /* {{{ void php_clear_warnings() */
35 : void php_clear_warnings(MYSQLI_WARNING *w)
36 4 : {
37 : MYSQLI_WARNING *n;
38 :
39 13 : while (w) {
40 5 : n = w;
41 5 : zval_dtor(&(w->reason));
42 5 : zval_dtor(&(w->sqlstate));
43 5 : w = w->next;
44 5 : efree(n);
45 : }
46 4 : }
47 : /* }}} */
48 :
49 :
50 : #ifndef MYSQLI_USE_MYSQLND
51 : /* {{{ MYSQLI_WARNING *php_new_warning */
52 : static
53 : MYSQLI_WARNING *php_new_warning(const char *reason, int errorno TSRMLS_DC)
54 : {
55 : MYSQLI_WARNING *w;
56 :
57 : w = (MYSQLI_WARNING *)ecalloc(1, sizeof(MYSQLI_WARNING));
58 :
59 : ZVAL_UTF8_STRING(&(w->reason), reason, ZSTR_DUPLICATE);
60 :
61 : ZVAL_UTF8_STRINGL(&(w->sqlstate), "HY000", sizeof("HY000") - 1, ZSTR_DUPLICATE);
62 :
63 : w->errorno = errorno;
64 :
65 : return w;
66 : }
67 : /* }}} */
68 :
69 :
70 : /* {{{ MYSQLI_WARNING *php_get_warnings(MYSQL *mysql TSRMLS_DC) */
71 : MYSQLI_WARNING *php_get_warnings(MYSQL *mysql TSRMLS_DC)
72 : {
73 : MYSQLI_WARNING *w, *first = NULL, *prev = NULL;
74 : MYSQL_RES *result;
75 : MYSQL_ROW row;
76 :
77 : if (mysql_real_query(mysql, "SHOW WARNINGS", 13)) {
78 : return NULL;
79 : }
80 :
81 : result = mysql_store_result(mysql);
82 :
83 : while ((row = mysql_fetch_row(result))) {
84 : w = php_new_warning(row[2], atoi(row[1]) TSRMLS_CC);
85 : if (!first) {
86 : first = w;
87 : }
88 : if (prev) {
89 : prev->next = w;
90 : }
91 : prev = w;
92 : }
93 : mysql_free_result(result);
94 : return first;
95 : }
96 : /* }}} */
97 : #else
98 : /* {{{ MYSQLI_WARNING *php_new_warning */
99 : static
100 : MYSQLI_WARNING *php_new_warning(const zval *reason, int errorno TSRMLS_DC)
101 5 : {
102 : MYSQLI_WARNING *w;
103 :
104 5 : w = (MYSQLI_WARNING *)ecalloc(1, sizeof(MYSQLI_WARNING));
105 :
106 5 : w->reason = *reason;
107 5 : zval_copy_ctor(&(w->reason));
108 : /*
109 : XXX: THIS JUST WON'T WORK IF 'character_set_system' is different
110 : than latin1 or utf8 !!!! We have to fix it by querying the server for its
111 : character_set_system and create appropriate convertor for anything but
112 : utf8/latin1 .
113 : */
114 5 : ZVAL_UTF8_STRINGL(&(w->reason), Z_STRVAL(w->reason), Z_STRLEN(w->reason), ZSTR_AUTOFREE);
115 :
116 5 : ZVAL_UTF8_STRINGL(&(w->sqlstate), "HY000", sizeof("HY000") - 1, ZSTR_DUPLICATE);
117 :
118 5 : w->errorno = errorno;
119 :
120 5 : return w;
121 : }
122 : /* }}} */
123 :
124 :
125 : /* {{{ MYSQLI_WARNING *php_get_warnings(MYSQL *mysql TSRMLS_DC) */
126 : MYSQLI_WARNING *php_get_warnings(MYSQL *mysql TSRMLS_DC)
127 4 : {
128 4 : MYSQLI_WARNING *w, *first = NULL, *prev = NULL;
129 : MYSQL_RES *result;
130 : zval *row;
131 :
132 4 : if (mysql_real_query(mysql, "SHOW WARNINGS", 13)) {
133 0 : return NULL;
134 : }
135 :
136 4 : result = mysql_use_result(mysql);
137 :
138 : for (;;) {
139 : zval **entry;
140 : int errno;
141 :
142 9 : MAKE_STD_ZVAL(row);
143 9 : mysqlnd_fetch_into(result, MYSQLND_FETCH_NUM, row, MYSQLND_MYSQLI);
144 9 : if (Z_TYPE_P(row) != IS_ARRAY) {
145 4 : zval_ptr_dtor(&row);
146 : break;
147 : }
148 5 : zend_hash_internal_pointer_reset(Z_ARRVAL_P(row));
149 : /* 0. we don't care about the first */
150 5 : zend_hash_move_forward(Z_ARRVAL_P(row));
151 :
152 : /* 1. Here comes the error no */
153 5 : zend_hash_get_current_data(Z_ARRVAL_P(row), (void **)&entry);
154 5 : convert_to_long_ex(entry);
155 5 : errno = Z_LVAL_PP(entry);
156 5 : zend_hash_move_forward(Z_ARRVAL_P(row));
157 :
158 : /* 2. Here comes the reason */
159 5 : zend_hash_get_current_data(Z_ARRVAL_P(row), (void **)&entry);
160 :
161 5 : w = php_new_warning(*entry, errno TSRMLS_CC);
162 : /*
163 : Don't destroy entry, because the row destroy will decrease
164 : the refcounter. Decreased twice then mysqlnd_free_result()
165 : will crash, because it will try to access already freed memory.
166 : */
167 5 : if (!first) {
168 4 : first = w;
169 : }
170 5 : if (prev) {
171 1 : prev->next = (void *)w;
172 : }
173 5 : prev = w;
174 :
175 5 : zval_ptr_dtor(&row);
176 5 : }
177 :
178 4 : mysql_free_result(result);
179 4 : return first;
180 : }
181 : /* }}} */
182 : #endif
183 :
184 :
185 : /* {{{ bool mysqli_warning::next() */
186 : PHP_METHOD(mysqli_warning, next)
187 3 : {
188 : MYSQLI_WARNING *w;
189 : zval *mysqli_warning;
190 3 : mysqli_object *obj = (mysqli_object *)zend_objects_get_address(getThis() TSRMLS_CC);
191 :
192 3 : if (obj->ptr) {
193 3 : if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O",
194 : &mysqli_warning, mysqli_warning_class_entry) == FAILURE) {
195 0 : return;
196 : }
197 :
198 3 : MYSQLI_FETCH_RESOURCE(w, MYSQLI_WARNING *, &mysqli_warning, "mysqli_warning", MYSQLI_STATUS_VALID);
199 :
200 3 : if (w->next) {
201 1 : w = w->next;
202 1 : ((MYSQLI_RESOURCE *)(obj->ptr))->ptr = w;
203 1 : RETURN_TRUE;
204 : }
205 : }
206 2 : RETURN_FALSE;
207 : }
208 : /* }}} */
209 :
210 :
211 : /* {{{ property mysqli_warning_message */
212 : static
213 : int mysqli_warning_message(mysqli_object *obj, zval **retval TSRMLS_DC)
214 4 : {
215 : MYSQLI_WARNING *w;
216 :
217 4 : if (!obj->ptr || !((MYSQLI_RESOURCE *)(obj->ptr))->ptr) {
218 0 : return FAILURE;
219 : }
220 :
221 4 : w = (MYSQLI_WARNING *)((MYSQLI_RESOURCE *)(obj->ptr))->ptr;
222 4 : MAKE_STD_ZVAL(*retval);
223 4 : **retval = w->reason;
224 4 : zval_copy_ctor(*retval);
225 4 : return SUCCESS;
226 : }
227 : /* }}} */
228 :
229 :
230 : /* {{{ property mysqli_warning_sqlstate */
231 : static
232 : int mysqli_warning_sqlstate(mysqli_object *obj, zval **retval TSRMLS_DC)
233 4 : {
234 : MYSQLI_WARNING *w;
235 :
236 4 : if (!obj->ptr || !((MYSQLI_RESOURCE *)(obj->ptr))->ptr) {
237 0 : return FAILURE;
238 : }
239 :
240 4 : w = (MYSQLI_WARNING *)((MYSQLI_RESOURCE *)(obj->ptr))->ptr;
241 4 : MAKE_STD_ZVAL(*retval);
242 4 : **retval = w->sqlstate;
243 4 : zval_copy_ctor(*retval);
244 4 : return SUCCESS;
245 : }
246 : /* }}} */
247 :
248 :
249 : /* {{{ property mysqli_warning_error */
250 : static
251 : int mysqli_warning_errno(mysqli_object *obj, zval **retval TSRMLS_DC)
252 4 : {
253 : MYSQLI_WARNING *w;
254 :
255 4 : if (!obj->ptr || !((MYSQLI_RESOURCE *)(obj->ptr))->ptr) {
256 0 : return FAILURE;
257 : }
258 4 : w = (MYSQLI_WARNING *)((MYSQLI_RESOURCE *)(obj->ptr))->ptr;
259 4 : MAKE_STD_ZVAL(*retval);
260 4 : ZVAL_LONG(*retval, w->errorno);
261 4 : return SUCCESS;
262 : }
263 : /* }}} */
264 :
265 : /* {{{ mysqli_warning_construct(object obj) */
266 : PHP_METHOD(mysqli_warning, __construct)
267 0 : {
268 : zval *z;
269 : mysqli_object *obj;
270 : MYSQL *hdl;
271 : MYSQLI_WARNING *w;
272 : MYSQLI_RESOURCE *mysqli_resource;
273 :
274 0 : if (ZEND_NUM_ARGS() != 1) {
275 0 : WRONG_PARAM_COUNT;
276 : }
277 0 : if (zend_parse_parameters(1 TSRMLS_CC, "o", &z)==FAILURE) {
278 0 : return;
279 : }
280 0 : obj = (mysqli_object *)zend_object_store_get_object(z TSRMLS_CC);\
281 :
282 0 : if (obj->zo.ce == mysqli_link_class_entry) {
283 : MY_MYSQL *mysql;
284 0 : MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &z, "mysqli_link", MYSQLI_STATUS_VALID);
285 0 : hdl = mysql->mysql;
286 0 : } else if (obj->zo.ce == mysqli_stmt_class_entry) {
287 : MY_STMT *stmt;
288 0 : MYSQLI_FETCH_RESOURCE(stmt, MY_STMT *, &z, "mysqli_stmt", MYSQLI_STATUS_VALID);
289 0 : hdl = mysqli_stmt_get_connection(stmt->stmt);
290 : } else {
291 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid class argument");
292 0 : RETURN_FALSE;
293 : }
294 :
295 0 : if (mysql_warning_count(hdl)) {
296 0 : w = php_get_warnings(hdl TSRMLS_CC);
297 : } else {
298 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "No warnings found");
299 0 : RETURN_FALSE;
300 : }
301 :
302 0 : mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
303 0 : mysqli_resource->ptr = mysqli_resource->info = (void *)w;
304 0 : mysqli_resource->status = MYSQLI_STATUS_VALID;
305 :
306 0 : if (!getThis() || !instanceof_function(Z_OBJCE_P(getThis()), mysqli_warning_class_entry TSRMLS_CC)) {
307 0 : MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_warning_class_entry);
308 : } else {
309 0 : ((mysqli_object *) zend_object_store_get_object(getThis() TSRMLS_CC))->ptr = mysqli_resource;
310 : }
311 :
312 : }
313 : /* }}} */
314 :
315 : /* {{{ mysqli_warning_methods */
316 : const zend_function_entry mysqli_warning_methods[] = {
317 : PHP_ME(mysqli_warning, __construct, NULL, ZEND_ACC_PROTECTED)
318 : PHP_ME(mysqli_warning, next, NULL, ZEND_ACC_PUBLIC)
319 : {NULL, NULL, NULL}
320 : };
321 : /* }}} */
322 :
323 : /* {{{ mysqli_warning_property_entries */
324 : const mysqli_property_entry mysqli_warning_property_entries[] = {
325 : {"message", sizeof("message") - 1, mysqli_warning_message, NULL},
326 : {"sqlstate", sizeof("sqlstate") - 1, mysqli_warning_sqlstate, NULL},
327 : {"errno", sizeof("errno") - 1, mysqli_warning_errno, NULL},
328 : {NULL, 0, NULL, NULL}
329 : };
330 : /* }}} */
331 :
332 : /* {{{ mysqli_warning_property_info_entries */
333 : zend_property_info mysqli_warning_property_info_entries[] = {
334 : {ZEND_ACC_PUBLIC, {"message"}, sizeof("message") - 1, 0, {NULL}, 0, NULL},
335 : {ZEND_ACC_PUBLIC, {"sqlstate"}, sizeof("sqlstate") - 1, 0, {NULL}, 0, NULL},
336 : {ZEND_ACC_PUBLIC, {"errno"}, sizeof("errno") - 1, 0, {NULL}, 0, NULL},
337 : {0, {NULL}, 0, 0, {NULL}, 0, NULL}
338 : };
339 : /* }}} */
340 :
341 :
342 : /*
343 : * Local variables:
344 : * tab-width: 4
345 : * c-basic-offset: 4
346 : * indent-tabs-mode: t
347 : * End:
348 : * vim600: noet sw=4 ts=4 fdm=marker
349 : * vim<600: noet sw=4 ts=4
350 : */
|