1 /*
2   +----------------------------------------------------------------------+
3   | Copyright (c) The PHP Group                                          |
4   +----------------------------------------------------------------------+
5   | This source file is subject to version 3.01 of the PHP license,      |
6   | that is bundled with this package in the file LICENSE, and is        |
7   | available through the world-wide-web at the following url:           |
8   | http://www.php.net/license/3_01.txt                                  |
9   | If you did not receive a copy of the PHP license and are unable to   |
10   | obtain it through the world-wide-web, please send a note to          |
11   | license@php.net so we can mail you a copy immediately.               |
12   +----------------------------------------------------------------------+
13   | Author: Georg Richter <georg@php.net>                                |
14   |         Andrey Hristov <andrey@php.net>                              |
15   +----------------------------------------------------------------------+
16 */
17 
18 #ifdef HAVE_CONFIG_H
19 #include "config.h"
20 #endif
21 
22 #include <signal.h>
23 
24 #include "php.h"
25 #include "php_ini.h"
26 #include "ext/standard/info.h"
27 #if defined(MYSQLI_USE_MYSQLND)
28 #include "php_mysqli_structs.h"
29 #endif
30 #include "mysqli_priv.h"
31 
32 #define CHECK_STATUS(value, quiet) \
33 	if (!obj->ptr || ((MYSQLI_RESOURCE *)obj->ptr)->status < value ) { \
34 		if (!quiet) { \
35 			zend_throw_error(NULL, "Property access is not allowed yet"); \
36 		} \
37 		return FAILURE; \
38 	} \
39 
40 #define MYSQLI_GET_MYSQL(statusval) \
41 MYSQL *p; \
42 if (!obj->ptr || !(MY_MYSQL *)((MYSQLI_RESOURCE *)(obj->ptr))->ptr) { \
43 	if (!quiet) { \
44 		zend_throw_error(NULL, "%s object is already closed", ZSTR_VAL(obj->zo.ce->name)); \
45 	} \
46 	return FAILURE; \
47 } else { \
48 	CHECK_STATUS(statusval, quiet);\
49     p = (MYSQL *)((MY_MYSQL *)((MYSQLI_RESOURCE *)(obj->ptr))->ptr)->mysql;\
50 }
51 
52 #define MYSQLI_GET_RESULT(statusval) \
53 MYSQL_RES *p; \
54 if (!obj->ptr) { \
55 	if (!quiet) { \
56 		zend_throw_error(NULL, "%s object is already closed", ZSTR_VAL(obj->zo.ce->name)); \
57 	} \
58 	return FAILURE; \
59 } else { \
60 	CHECK_STATUS(statusval, quiet);\
61 	p = (MYSQL_RES *)((MYSQLI_RESOURCE *)(obj->ptr))->ptr; \
62 }
63 
64 #define MYSQLI_GET_STMT(statusval) \
65 MYSQL_STMT *p; \
66 if (!obj->ptr) { \
67 	if (!quiet) { \
68 		zend_throw_error(NULL, "%s object is already closed", ZSTR_VAL(obj->zo.ce->name)); \
69 	} \
70 	return FAILURE; \
71 } else { \
72 	CHECK_STATUS(statusval, quiet); \
73 	p = (MYSQL_STMT *)((MY_STMT *)((MYSQLI_RESOURCE *)(obj->ptr))->ptr)->stmt; \
74 }
75 
76 #define MYSQLI_MAP_PROPERTY_FUNC_LONG( __func, __int_func, __get_type, __ret_type, __ret_type_sprint_mod)\
77 static int __func(mysqli_object *obj, zval *retval, zend_bool quiet) \
78 {\
79 	__ret_type l;\
80 	__get_type;\
81 	if (!p) {\
82 		ZVAL_NULL(retval);\
83 	} else {\
84 		l = (__ret_type)__int_func(p);\
85 		if (l < ZEND_LONG_MAX) {\
86 			ZVAL_LONG(retval, (zend_long) l);\
87 		} else { \
88 			ZVAL_NEW_STR(retval, strpprintf(0, __ret_type_sprint_mod, l)); \
89 		} \
90 	} \
91 	return SUCCESS; \
92 }
93 
94 #define MYSQLI_MAP_PROPERTY_FUNC_STRING(__func, __int_func, __get_type)\
95 static int __func(mysqli_object *obj, zval *retval, zend_bool quiet)\
96 {\
97 	char *c;\
98 	__get_type;\
99 	if (!p) {\
100 		ZVAL_NULL(retval);\
101 	} else {\
102 		c = (char *)__int_func(p);\
103 		if (!c) {\
104 			ZVAL_NULL(retval);\
105 		} else {\
106 			ZVAL_STRING(retval, c);\
107 		}\
108 	}\
109 	return SUCCESS; \
110 }
111 
112 /* {{{ property link_client_version_read */
link_client_version_read(mysqli_object * obj,zval * retval,zend_bool quiet)113 static int link_client_version_read(mysqli_object *obj, zval *retval, zend_bool quiet)
114 {
115 	ZVAL_LONG(retval, MYSQL_VERSION_ID);
116 
117 	return SUCCESS;
118 }
119 /* }}} */
120 
121 /* {{{ property link_client_info_read */
link_client_info_read(mysqli_object * obj,zval * retval,zend_bool quiet)122 static int link_client_info_read(mysqli_object *obj, zval *retval, zend_bool quiet)
123 {
124 	CHECK_STATUS(MYSQLI_STATUS_INITIALIZED, quiet);
125 	ZVAL_STRING(retval, MYSQL_SERVER_VERSION);
126 
127 	return SUCCESS;
128 }
129 /* }}} */
130 
131 /* {{{ property link_connect_errno_read */
link_connect_errno_read(mysqli_object * obj,zval * retval,zend_bool quiet)132 static int link_connect_errno_read(mysqli_object *obj, zval *retval, zend_bool quiet)
133 {
134 	ZVAL_LONG(retval, (zend_long)MyG(error_no));
135 
136 	return SUCCESS;
137 }
138 /* }}} */
139 
140 /* {{{ property link_connect_error_read */
link_connect_error_read(mysqli_object * obj,zval * retval,zend_bool quiet)141 static int link_connect_error_read(mysqli_object *obj, zval *retval, zend_bool quiet)
142 {
143 	if (MyG(error_msg)) {
144 		ZVAL_STRING(retval, MyG(error_msg));
145 	} else {
146 		ZVAL_NULL(retval);
147 	}
148 
149 	return SUCCESS;
150 }
151 /* }}} */
152 
153 /* {{{ property link_affected_rows_read */
link_affected_rows_read(mysqli_object * obj,zval * retval,zend_bool quiet)154 static int link_affected_rows_read(mysqli_object *obj, zval *retval, zend_bool quiet)
155 {
156 	MY_MYSQL *mysql;
157 	my_ulonglong rc;
158 
159 	CHECK_STATUS(MYSQLI_STATUS_INITIALIZED, quiet);
160 
161  	mysql = (MY_MYSQL *)((MYSQLI_RESOURCE *)(obj->ptr))->ptr;
162 
163 	if (!mysql) {
164 		ZVAL_NULL(retval);
165 	} else {
166 		CHECK_STATUS(MYSQLI_STATUS_VALID, quiet);
167 
168 		rc = mysql_affected_rows(mysql->mysql);
169 
170 		if (rc == (my_ulonglong) -1) {
171 			ZVAL_LONG(retval, -1);
172 			return SUCCESS;
173 		}
174 
175 		if (rc < ZEND_LONG_MAX) {
176 			ZVAL_LONG(retval, (zend_long) rc);
177 		} else {
178 			ZVAL_NEW_STR(retval, strpprintf(0, MYSQLI_LLU_SPEC, rc));
179 		}
180 	}
181 
182 	return SUCCESS;
183 }
184 /* }}} */
185 
186 /* {{{ property link_error_list_read */
link_error_list_read(mysqli_object * obj,zval * retval,zend_bool quiet)187 static int link_error_list_read(mysqli_object *obj, zval *retval, zend_bool quiet)
188 {
189 	MY_MYSQL *mysql;
190 
191 	CHECK_STATUS(MYSQLI_STATUS_VALID, quiet);
192 
193  	mysql = (MY_MYSQL *)((MYSQLI_RESOURCE *)(obj->ptr))->ptr;
194 
195 	if (mysql) {
196 		array_init(retval);
197 #ifdef MYSQLI_USE_MYSQLND
198 		if (1) {
199 			MYSQLND_ERROR_LIST_ELEMENT * message;
200 			zend_llist_position pos;
201 			for (message = (MYSQLND_ERROR_LIST_ELEMENT *) zend_llist_get_first_ex(&mysql->mysql->data->error_info->error_list, &pos);
202 				 message;
203 				 message = (MYSQLND_ERROR_LIST_ELEMENT *) zend_llist_get_next_ex(&mysql->mysql->data->error_info->error_list, &pos))
204 			{
205 				zval single_error;
206 				array_init(&single_error);
207 				add_assoc_long_ex(&single_error, "errno", sizeof("errno") - 1, message->error_no);
208 				add_assoc_string_ex(&single_error, "sqlstate", sizeof("sqlstate") - 1, message->sqlstate);
209 				add_assoc_string_ex(&single_error, "error", sizeof("error") - 1, message->error);
210 				add_next_index_zval(retval, &single_error);
211 			}
212 		}
213 #else
214 		if (mysql_errno(mysql->mysql)) {
215 			zval single_error;
216 			array_init(&single_error);
217 			add_assoc_long_ex(&single_error, "errno", sizeof("errno") - 1, mysql_errno(mysql->mysql));
218 			add_assoc_string_ex(&single_error, "sqlstate", sizeof("sqlstate") - 1, mysql_sqlstate(mysql->mysql));
219 			add_assoc_string_ex(&single_error, "error", sizeof("error") - 1, mysql_error(mysql->mysql));
220 			add_next_index_zval(retval, &single_error);
221 		}
222 #endif
223 	} else {
224 		ZVAL_EMPTY_ARRAY(retval);
225 	}
226 
227 	return SUCCESS;
228 }
229 /* }}} */
230 
231 /* link properties */
MYSQLI_MAP_PROPERTY_FUNC_LONG(link_errno_read,mysql_errno,MYSQLI_GET_MYSQL (MYSQLI_STATUS_INITIALIZED),zend_ulong,ZEND_ULONG_FMT)232 MYSQLI_MAP_PROPERTY_FUNC_LONG(link_errno_read, mysql_errno, MYSQLI_GET_MYSQL(MYSQLI_STATUS_INITIALIZED), zend_ulong, ZEND_ULONG_FMT)
233 MYSQLI_MAP_PROPERTY_FUNC_STRING(link_error_read, mysql_error, MYSQLI_GET_MYSQL(MYSQLI_STATUS_INITIALIZED))
234 MYSQLI_MAP_PROPERTY_FUNC_LONG(link_field_count_read, mysql_field_count, MYSQLI_GET_MYSQL(MYSQLI_STATUS_VALID), zend_ulong, ZEND_ULONG_FMT)
235 MYSQLI_MAP_PROPERTY_FUNC_STRING(link_host_info_read, mysql_get_host_info, MYSQLI_GET_MYSQL(MYSQLI_STATUS_VALID))
236 MYSQLI_MAP_PROPERTY_FUNC_STRING(link_info_read, mysql_info, MYSQLI_GET_MYSQL(MYSQLI_STATUS_VALID))
237 MYSQLI_MAP_PROPERTY_FUNC_LONG(link_insert_id_read, mysql_insert_id, MYSQLI_GET_MYSQL(MYSQLI_STATUS_VALID), my_ulonglong, MYSQLI_LLU_SPEC)
238 MYSQLI_MAP_PROPERTY_FUNC_LONG(link_protocol_version_read, mysql_get_proto_info, MYSQLI_GET_MYSQL(MYSQLI_STATUS_VALID), zend_ulong, ZEND_ULONG_FMT)
239 MYSQLI_MAP_PROPERTY_FUNC_STRING(link_server_info_read, mysql_get_server_info, MYSQLI_GET_MYSQL(MYSQLI_STATUS_VALID))
240 MYSQLI_MAP_PROPERTY_FUNC_LONG(link_server_version_read, mysql_get_server_version, MYSQLI_GET_MYSQL(MYSQLI_STATUS_VALID), zend_ulong, ZEND_ULONG_FMT)
241 MYSQLI_MAP_PROPERTY_FUNC_STRING(link_sqlstate_read, mysql_sqlstate, MYSQLI_GET_MYSQL(MYSQLI_STATUS_VALID))
242 MYSQLI_MAP_PROPERTY_FUNC_LONG(link_thread_id_read, mysql_thread_id, MYSQLI_GET_MYSQL(MYSQLI_STATUS_VALID), zend_ulong, ZEND_ULONG_FMT)
243 MYSQLI_MAP_PROPERTY_FUNC_LONG(link_warning_count_read, mysql_warning_count, MYSQLI_GET_MYSQL(MYSQLI_STATUS_VALID), zend_ulong, ZEND_ULONG_FMT)
244 
245 /* result properties */
246 
247 /* {{{ property result_type_read */
248 static int result_type_read(mysqli_object *obj, zval *retval, zend_bool quiet)
249 {
250 	MYSQL_RES *p;
251 
252 	CHECK_STATUS(MYSQLI_STATUS_VALID, quiet);
253  	p = (MYSQL_RES *)((MYSQLI_RESOURCE *)(obj->ptr))->ptr;
254 
255 	if (!p) {
256 		ZVAL_NULL(retval);
257 	} else {
258 		ZVAL_LONG(retval, mysqli_result_is_unbuffered(p) ? MYSQLI_USE_RESULT:MYSQLI_STORE_RESULT);
259 	}
260 
261 	return SUCCESS;
262 }
263 /* }}} */
264 
265 /* {{{ property result_lengths_read */
result_lengths_read(mysqli_object * obj,zval * retval,zend_bool quiet)266 static int result_lengths_read(mysqli_object *obj, zval *retval, zend_bool quiet)
267 {
268 	MYSQL_RES *p;
269 #ifdef MYSQLI_USE_MYSQLND
270 	const size_t *ret;
271 #else
272 	const zend_ulong *ret;
273 #endif
274 	uint32_t field_count;
275 
276 	CHECK_STATUS(MYSQLI_STATUS_VALID, quiet);
277 	p = (MYSQL_RES *)((MYSQLI_RESOURCE *)(obj->ptr))->ptr;
278 	field_count = mysql_num_fields(p);
279 	if (!p || !field_count || !(ret = mysql_fetch_lengths(p))) {
280 		ZVAL_NULL(retval);
281 	} else {
282 		zend_ulong i;
283 
284 		array_init(retval);
285 
286 		for (i = 0; i < field_count; i++) {
287 			add_index_long(retval, i, ret[i]);
288 		}
289 	}
290 
291 	return SUCCESS;
292 }
293 /* }}} */
294 
MYSQLI_MAP_PROPERTY_FUNC_LONG(result_current_field_read,mysql_field_tell,MYSQLI_GET_RESULT (MYSQLI_STATUS_VALID),zend_ulong,ZEND_ULONG_FMT)295 MYSQLI_MAP_PROPERTY_FUNC_LONG(result_current_field_read, mysql_field_tell, MYSQLI_GET_RESULT(MYSQLI_STATUS_VALID), zend_ulong, ZEND_ULONG_FMT)
296 MYSQLI_MAP_PROPERTY_FUNC_LONG(result_field_count_read, mysql_num_fields, MYSQLI_GET_RESULT(MYSQLI_STATUS_VALID), zend_ulong, ZEND_ULONG_FMT)
297 MYSQLI_MAP_PROPERTY_FUNC_LONG(result_num_rows_read, mysql_num_rows, MYSQLI_GET_RESULT(MYSQLI_STATUS_VALID), my_ulonglong, MYSQLI_LLU_SPEC)
298 
299 /* statement properties */
300 
301 /* {{{ property stmt_id_read */
302 static int stmt_id_read(mysqli_object *obj, zval *retval, zend_bool quiet)
303 {
304 	MY_STMT *p;
305 
306 	CHECK_STATUS(MYSQLI_STATUS_VALID, quiet);
307 
308  	p = (MY_STMT*)((MYSQLI_RESOURCE *)(obj->ptr))->ptr;
309 
310 	if (!p) {
311 		ZVAL_NULL(retval);
312 	} else {
313 		ZVAL_LONG(retval, mysqli_stmt_get_id(p->stmt));
314 	}
315 
316 	return SUCCESS;
317 }
318 /* }}} */
319 
320 /* {{{ property stmt_affected_rows_read */
stmt_affected_rows_read(mysqli_object * obj,zval * retval,zend_bool quiet)321 static int stmt_affected_rows_read(mysqli_object *obj, zval *retval, zend_bool quiet)
322 {
323 	MY_STMT *p;
324 	my_ulonglong rc;
325 
326 	CHECK_STATUS(MYSQLI_STATUS_VALID, quiet);
327 
328  	p = (MY_STMT *)((MYSQLI_RESOURCE *)(obj->ptr))->ptr;
329 
330 	if (!p) {
331 		ZVAL_NULL(retval);
332 	} else {
333 		rc = mysql_stmt_affected_rows(p->stmt);
334 
335 		if (rc == (my_ulonglong) -1) {
336 			ZVAL_LONG(retval, -1);
337 			return SUCCESS;
338 		}
339 
340 		if (rc < ZEND_LONG_MAX) {
341 			ZVAL_LONG(retval, (zend_long) rc);
342 		} else {
343 			ZVAL_NEW_STR(retval, strpprintf(0, MYSQLI_LLU_SPEC, rc));
344 		}
345 	}
346 
347 	return SUCCESS;
348 }
349 /* }}} */
350 
351 /* {{{ property stmt_error_list_read */
stmt_error_list_read(mysqli_object * obj,zval * retval,zend_bool quiet)352 static int stmt_error_list_read(mysqli_object *obj, zval *retval, zend_bool quiet)
353 {
354 	MY_STMT * stmt;
355 
356 	CHECK_STATUS(MYSQLI_STATUS_INITIALIZED, quiet);
357 
358  	stmt = (MY_STMT *)((MYSQLI_RESOURCE *)(obj->ptr))->ptr;
359 	if (stmt && stmt->stmt) {
360 		array_init(retval);
361 #ifdef MYSQLI_USE_MYSQLND
362 		if (stmt->stmt->data && stmt->stmt->data->error_info) {
363 			MYSQLND_ERROR_LIST_ELEMENT * message;
364 			zend_llist_position pos;
365 			for (message = (MYSQLND_ERROR_LIST_ELEMENT *) zend_llist_get_first_ex(&stmt->stmt->data->error_info->error_list, &pos);
366 				 message;
367 				 message = (MYSQLND_ERROR_LIST_ELEMENT *) zend_llist_get_next_ex(&stmt->stmt->data->error_info->error_list, &pos))
368 			{
369 				zval single_error;
370 				array_init(&single_error);
371 				add_assoc_long_ex(&single_error, "errno", sizeof("errno") - 1, message->error_no);
372 				add_assoc_string_ex(&single_error, "sqlstate", sizeof("sqlstate") - 1, message->sqlstate);
373 				add_assoc_string_ex(&single_error, "error", sizeof("error") - 1, message->error);
374 				add_next_index_zval(retval, &single_error);
375 			}
376 		}
377 #else
378 		if (mysql_stmt_errno(stmt->stmt)) {
379 			zval single_error;
380 			array_init(&single_error);
381 			add_assoc_long_ex(&single_error, "errno", sizeof("errno") - 1, mysql_stmt_errno(stmt->stmt));
382 			add_assoc_string_ex(&single_error, "sqlstate", sizeof("sqlstate") - 1, mysql_stmt_sqlstate(stmt->stmt));
383 			add_assoc_string_ex(&single_error, "error", sizeof("error") - 1, mysql_stmt_error(stmt->stmt));
384 			add_next_index_zval(retval, &single_error);
385 		}
386 #endif
387 	} else {
388 		ZVAL_EMPTY_ARRAY(retval);
389 	}
390 
391 	return SUCCESS;
392 }
393 /* }}} */
394 
395 MYSQLI_MAP_PROPERTY_FUNC_LONG(stmt_insert_id_read, mysql_stmt_insert_id, MYSQLI_GET_STMT(MYSQLI_STATUS_VALID), my_ulonglong, MYSQLI_LLU_SPEC)
396 MYSQLI_MAP_PROPERTY_FUNC_LONG(stmt_num_rows_read, mysql_stmt_num_rows, MYSQLI_GET_STMT(MYSQLI_STATUS_VALID), my_ulonglong, MYSQLI_LLU_SPEC)
397 MYSQLI_MAP_PROPERTY_FUNC_LONG(stmt_param_count_read, mysql_stmt_param_count, MYSQLI_GET_STMT(MYSQLI_STATUS_VALID), zend_ulong, ZEND_ULONG_FMT)
398 MYSQLI_MAP_PROPERTY_FUNC_LONG(stmt_field_count_read, mysql_stmt_field_count, MYSQLI_GET_STMT(MYSQLI_STATUS_VALID), zend_ulong, ZEND_ULONG_FMT)
399 MYSQLI_MAP_PROPERTY_FUNC_LONG(stmt_errno_read, mysql_stmt_errno, MYSQLI_GET_STMT(MYSQLI_STATUS_INITIALIZED), zend_ulong, ZEND_ULONG_FMT)
400 MYSQLI_MAP_PROPERTY_FUNC_STRING(stmt_error_read, mysql_stmt_error, MYSQLI_GET_STMT(MYSQLI_STATUS_INITIALIZED))
401 MYSQLI_MAP_PROPERTY_FUNC_STRING(stmt_sqlstate_read, mysql_stmt_sqlstate, MYSQLI_GET_STMT(MYSQLI_STATUS_INITIALIZED))
402 
403 /* }}} */
404 const mysqli_property_entry mysqli_link_property_entries[] = {
405 	{"affected_rows", 	sizeof("affected_rows") - 1,	link_affected_rows_read, NULL},
406 	{"client_info", 	sizeof("client_info") - 1,		link_client_info_read, NULL},
407 	{"client_version",	sizeof("client_version") - 1,	link_client_version_read, NULL},
408 	{"connect_errno",	sizeof("connect_errno") - 1,	link_connect_errno_read, NULL},
409 	{"connect_error",	sizeof("connect_error") - 1,	link_connect_error_read, NULL},
410 	{"errno",			sizeof("errno") - 1,			link_errno_read, NULL},
411 	{"error",			sizeof("error") - 1,			link_error_read, NULL},
412 	{"error_list",		sizeof("error_list") - 1,		link_error_list_read, NULL},
413 	{"field_count",		sizeof("field_count") - 1,		link_field_count_read, NULL},
414 	{"host_info",		sizeof("host_info") - 1,		link_host_info_read, NULL},
415 	{"info",			sizeof("info") - 1,				link_info_read, NULL},
416 	{"insert_id",		sizeof("insert_id") - 1,		link_insert_id_read, NULL},
417 	{"server_info",		sizeof("server_info") - 1,		link_server_info_read, NULL},
418 	{"server_version",	sizeof("server_version") - 1,	link_server_version_read, NULL},
419 	{"sqlstate",		sizeof("sqlstate") - 1,			link_sqlstate_read, NULL},
420 	{"protocol_version",sizeof("protocol_version") - 1,	link_protocol_version_read, NULL},
421 	{"thread_id",		sizeof("thread_id") - 1, 		link_thread_id_read, NULL},
422 	{"warning_count",	sizeof("warning_count") - 1, 	link_warning_count_read, NULL},
423 	{NULL, 0, NULL, NULL}
424 };
425 
426 
427 const mysqli_property_entry mysqli_result_property_entries[] = {
428 	{"current_field",sizeof("current_field")-1,	result_current_field_read, NULL},
429 	{"field_count", sizeof("field_count") - 1,	result_field_count_read, NULL},
430 	{"lengths", 	sizeof("lengths") - 1,		result_lengths_read, NULL},
431 	{"num_rows", 	sizeof("num_rows") - 1,		result_num_rows_read, NULL},
432 	{"type", 		sizeof("type") - 1,			result_type_read, NULL},
433 	{NULL, 0, NULL, NULL}
434 };
435 
436 const mysqli_property_entry mysqli_stmt_property_entries[] = {
437 	{"affected_rows", sizeof("affected_rows")-1,stmt_affected_rows_read, NULL},
438 	{"insert_id",	sizeof("insert_id") - 1, 	stmt_insert_id_read, NULL},
439 	{"num_rows",	sizeof("num_rows") - 1, 	stmt_num_rows_read, NULL},
440 	{"param_count", sizeof("param_count") - 1,	stmt_param_count_read, NULL},
441 	{"field_count", sizeof("field_count") - 1,	stmt_field_count_read, NULL},
442 	{"errno",		sizeof("errno") - 1,		stmt_errno_read, NULL},
443 	{"error",		sizeof("error") - 1, 		stmt_error_read, NULL},
444 	{"error_list",	sizeof("error_list") - 1, 	stmt_error_list_read, NULL},
445 	{"sqlstate",	sizeof("sqlstate") - 1,		stmt_sqlstate_read, NULL},
446 	{"id",			sizeof("id") - 1,			stmt_id_read, NULL},
447 	{NULL, 0, NULL, NULL}
448 };
449