This source file includes following definitions.
- php_mysqlnd_free_field_metadata
- MYSQLND_METHOD
- MYSQLND_METHOD
- MYSQLND_METHOD
- MYSQLND_METHOD
- MYSQLND_CLASS_METHODS_START
- mysqlnd_result_metadata_get_methods
- _mysqlnd_plugin_get_plugin_result_metadata_data
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 #include "php.h"
23 #include "mysqlnd.h"
24 #include "mysqlnd_priv.h"
25 #include "mysqlnd_result.h"
26 #include "mysqlnd_wireprotocol.h"
27 #include "mysqlnd_debug.h"
28 #include "ext/standard/basic_functions.h"
29
30
31
32 static void
33 php_mysqlnd_free_field_metadata(MYSQLND_FIELD *meta, zend_bool persistent)
34 {
35 if (meta) {
36 if (meta->root) {
37 mnd_pefree(meta->root, persistent);
38 meta->root = NULL;
39 }
40 if (meta->def) {
41 mnd_pefree(meta->def, persistent);
42 meta->def = NULL;
43 }
44 if (meta->sname) {
45 zend_string_release(meta->sname);
46 }
47 }
48 }
49
50
51
52 static enum_func_status
53 MYSQLND_METHOD(mysqlnd_res_meta, read_metadata)(MYSQLND_RES_METADATA * const meta, MYSQLND_CONN_DATA * conn)
54 {
55 unsigned int i = 0;
56 MYSQLND_PACKET_RES_FIELD * field_packet;
57
58 DBG_ENTER("mysqlnd_res_meta::read_metadata");
59
60 field_packet = conn->protocol->m.get_result_field_packet(conn->protocol, FALSE);
61 if (!field_packet) {
62 SET_OOM_ERROR(*conn->error_info);
63 DBG_RETURN(FAIL);
64 }
65 field_packet->persistent_alloc = meta->persistent;
66 for (;i < meta->field_count; i++) {
67 zend_ulong idx;
68
69 if (meta->fields[i].root) {
70
71 mnd_pefree(meta->fields[i].root, meta->persistent);
72 meta->fields[i].root = NULL;
73 }
74
75 field_packet->metadata = &(meta->fields[i]);
76 if (FAIL == PACKET_READ(field_packet, conn)) {
77 PACKET_FREE(field_packet);
78 DBG_RETURN(FAIL);
79 }
80 if (field_packet->error_info.error_no) {
81 COPY_CLIENT_ERROR(*conn->error_info, field_packet->error_info);
82
83 PACKET_FREE(field_packet);
84 DBG_RETURN(FAIL);
85 }
86
87 if (field_packet->stupid_list_fields_eof == TRUE) {
88 meta->field_count = i;
89 break;
90 }
91
92 if (mysqlnd_ps_fetch_functions[meta->fields[i].type].func == NULL) {
93 DBG_ERR_FMT("Unknown type %u sent by the server. Please send a report to the developers",
94 meta->fields[i].type);
95 php_error_docref(NULL, E_WARNING,
96 "Unknown type %u sent by the server. "
97 "Please send a report to the developers",
98 meta->fields[i].type);
99 PACKET_FREE(field_packet);
100 DBG_RETURN(FAIL);
101 }
102 if (meta->fields[i].type == MYSQL_TYPE_BIT) {
103 size_t field_len;
104 DBG_INF("BIT");
105 ++meta->bit_fields_count;
106
107 field_len = meta->fields[i].length / 8;
108
109
110
111
112 if (meta->fields[i].length % 8) {
113 ++field_len;
114 }
115 switch (field_len) {
116 case 8:
117 case 7:
118 case 6:
119 case 5:
120 meta->bit_fields_total_len += 20;
121 break;
122 case 4:
123 meta->bit_fields_total_len += 10;
124 break;
125 case 3:
126 meta->bit_fields_total_len += 8;
127 break;
128 case 2:
129 meta->bit_fields_total_len += 5;
130 break;
131 case 1:
132 meta->bit_fields_total_len += 3;
133 break;
134 }
135 }
136
137
138 if ((meta->zend_hash_keys[i].is_numeric = ZEND_HANDLE_NUMERIC(field_packet->metadata->sname, idx))) {
139 meta->zend_hash_keys[i].key = idx;
140 }
141 }
142 PACKET_FREE(field_packet);
143
144 DBG_RETURN(PASS);
145 }
146
147
148
149
150 static void
151 MYSQLND_METHOD(mysqlnd_res_meta, free)(MYSQLND_RES_METADATA * meta)
152 {
153 int i;
154 MYSQLND_FIELD *fields;
155 DBG_ENTER("mysqlnd_res_meta::free");
156 DBG_INF_FMT("persistent=%u", meta->persistent);
157
158 if ((fields = meta->fields)) {
159 DBG_INF("Freeing fields metadata");
160 i = meta->field_count;
161 while (i--) {
162 php_mysqlnd_free_field_metadata(fields++, meta->persistent);
163 }
164 mnd_pefree(meta->fields, meta->persistent);
165 meta->fields = NULL;
166 }
167
168 if (meta->zend_hash_keys) {
169 DBG_INF("Freeing zend_hash_keys");
170 mnd_pefree(meta->zend_hash_keys, meta->persistent);
171 meta->zend_hash_keys = NULL;
172 }
173 DBG_INF("Freeing metadata structure");
174 mnd_pefree(meta, meta->persistent);
175
176 DBG_VOID_RETURN;
177 }
178
179
180
181
182 static MYSQLND_RES_METADATA *
183 MYSQLND_METHOD(mysqlnd_res_meta, clone_metadata)(const MYSQLND_RES_METADATA * const meta, zend_bool persistent)
184 {
185 unsigned int i;
186
187 MYSQLND_RES_METADATA * new_meta = NULL;
188 MYSQLND_FIELD * new_fields;
189 MYSQLND_FIELD * orig_fields = meta->fields;
190 size_t len = meta->field_count * sizeof(struct mysqlnd_field_hash_key);
191
192 DBG_ENTER("mysqlnd_res_meta::clone_metadata");
193 DBG_INF_FMT("persistent=%u", persistent);
194
195 new_meta = mnd_pecalloc(1, sizeof(MYSQLND_RES_METADATA), persistent);
196 if (!new_meta) {
197 goto oom;
198 }
199 new_meta->persistent = persistent;
200 new_meta->m = meta->m;
201
202 new_fields = mnd_pecalloc(meta->field_count + 1, sizeof(MYSQLND_FIELD), persistent);
203 if (!new_fields) {
204 goto oom;
205 }
206
207 new_meta->zend_hash_keys = mnd_pemalloc(len, persistent);
208 if (!new_meta->zend_hash_keys) {
209 goto oom;
210 }
211 memcpy(new_meta->zend_hash_keys, meta->zend_hash_keys, len);
212
213
214
215
216
217 memcpy(new_fields, orig_fields, (meta->field_count) * sizeof(MYSQLND_FIELD));
218 for (i = 0; i < meta->field_count; i++) {
219
220 new_fields[i].root = mnd_pemalloc(orig_fields[i].root_len, persistent);
221
222 if (!new_fields[i].root) {
223 goto oom;
224 }
225
226 memcpy(new_fields[i].root, orig_fields[i].root, new_fields[i].root_len);
227
228 if (orig_fields[i].sname) {
229 new_fields[i].sname = zend_string_copy(orig_fields[i].sname);
230 new_fields[i].name = ZSTR_VAL(new_fields[i].sname);
231 new_fields[i].name_length = ZSTR_LEN(new_fields[i].sname);
232 }
233
234 if (orig_fields[i].org_name && orig_fields[i].org_name != mysqlnd_empty_string) {
235 new_fields[i].org_name = new_fields[i].root +
236 (orig_fields[i].org_name - orig_fields[i].root);
237 }
238 if (orig_fields[i].table && orig_fields[i].table != mysqlnd_empty_string) {
239 new_fields[i].table = new_fields[i].root +
240 (orig_fields[i].table - orig_fields[i].root);
241 }
242 if (orig_fields[i].org_table && orig_fields[i].org_table != mysqlnd_empty_string) {
243 new_fields[i].org_table = new_fields[i].root +
244 (orig_fields[i].org_table - orig_fields[i].root);
245 }
246 if (orig_fields[i].db && orig_fields[i].db != mysqlnd_empty_string) {
247 new_fields[i].db = new_fields[i].root + (orig_fields[i].db - orig_fields[i].root);
248 }
249 if (orig_fields[i].catalog && orig_fields[i].catalog != mysqlnd_empty_string) {
250 new_fields[i].catalog = new_fields[i].root + (orig_fields[i].catalog - orig_fields[i].root);
251 }
252
253 if (orig_fields[i].def) {
254 new_fields[i].def = mnd_pemalloc(orig_fields[i].def_length + 1, persistent);
255 if (!new_fields[i].def) {
256 goto oom;
257 }
258
259 memcpy(new_fields[i].def, orig_fields[i].def, orig_fields[i].def_length + 1);
260 }
261 }
262 new_meta->current_field = 0;
263 new_meta->field_count = meta->field_count;
264
265 new_meta->fields = new_fields;
266
267 DBG_RETURN(new_meta);
268 oom:
269 if (new_meta) {
270 new_meta->m->free_metadata(new_meta);
271 new_meta = NULL;
272 }
273 DBG_RETURN(NULL);
274 }
275
276
277
278
279 static const MYSQLND_FIELD *
280 MYSQLND_METHOD(mysqlnd_res_meta, fetch_field)(MYSQLND_RES_METADATA * const meta)
281 {
282 DBG_ENTER("mysqlnd_res_meta::fetch_field");
283 if (meta->current_field >= meta->field_count) {
284 DBG_INF("no more fields");
285 DBG_RETURN(NULL);
286 }
287 DBG_INF_FMT("name=%s max_length=%u",
288 meta->fields[meta->current_field].name? meta->fields[meta->current_field].name:"",
289 meta->fields[meta->current_field].max_length);
290 DBG_RETURN(&meta->fields[meta->current_field++]);
291 }
292
293
294
295
296 static const MYSQLND_FIELD *
297 MYSQLND_METHOD(mysqlnd_res_meta, fetch_field_direct)(const MYSQLND_RES_METADATA * const meta, const MYSQLND_FIELD_OFFSET fieldnr)
298 {
299 DBG_ENTER("mysqlnd_res_meta::fetch_field_direct");
300 DBG_INF_FMT("fieldnr=%u", fieldnr);
301 DBG_INF_FMT("name=%s max_length=%u",
302 meta->fields[meta->current_field].name? meta->fields[meta->current_field].name:"",
303 meta->fields[meta->current_field].max_length);
304 DBG_RETURN(&meta->fields[fieldnr]);
305 }
306
307
308
309
310 static const MYSQLND_FIELD *
311 MYSQLND_METHOD(mysqlnd_res_meta, fetch_fields)(MYSQLND_RES_METADATA * const meta)
312 {
313 DBG_ENTER("mysqlnd_res_meta::fetch_fields");
314 DBG_RETURN(meta->fields);
315 }
316
317
318
319
320 static MYSQLND_FIELD_OFFSET
321 MYSQLND_METHOD(mysqlnd_res_meta, field_tell)(const MYSQLND_RES_METADATA * const meta)
322 {
323 return meta->current_field;
324 }
325
326
327
328
329 static MYSQLND_FIELD_OFFSET
330 MYSQLND_METHOD(mysqlnd_res_meta, field_seek)(MYSQLND_RES_METADATA * const meta, const MYSQLND_FIELD_OFFSET field_offset)
331 {
332 MYSQLND_FIELD_OFFSET return_value = 0;
333 DBG_ENTER("mysqlnd_res_meta::fetch_fields");
334 return_value = meta->current_field;
335 meta->current_field = field_offset;
336 DBG_RETURN(return_value);
337 }
338
339
340 static
341 MYSQLND_CLASS_METHODS_START(mysqlnd_res_meta)
342 MYSQLND_METHOD(mysqlnd_res_meta, fetch_field),
343 MYSQLND_METHOD(mysqlnd_res_meta, fetch_field_direct),
344 MYSQLND_METHOD(mysqlnd_res_meta, fetch_fields),
345 MYSQLND_METHOD(mysqlnd_res_meta, field_tell),
346 MYSQLND_METHOD(mysqlnd_res_meta, field_seek),
347 MYSQLND_METHOD(mysqlnd_res_meta, read_metadata),
348 MYSQLND_METHOD(mysqlnd_res_meta, clone_metadata),
349 MYSQLND_METHOD(mysqlnd_res_meta, free),
350 MYSQLND_CLASS_METHODS_END;
351
352
353
354 PHPAPI MYSQLND_RES_METADATA *
355 mysqlnd_result_meta_init(unsigned int field_count, zend_bool persistent)
356 {
357 size_t alloc_size = sizeof(MYSQLND_RES_METADATA) + mysqlnd_plugin_count() * sizeof(void *);
358 MYSQLND_RES_METADATA *ret = mnd_pecalloc(1, alloc_size, persistent);
359 DBG_ENTER("mysqlnd_result_meta_init");
360 DBG_INF_FMT("persistent=%u", persistent);
361
362 do {
363 if (!ret) {
364 break;
365 }
366 ret->m = & mysqlnd_mysqlnd_res_meta_methods;
367
368 ret->persistent = persistent;
369 ret->field_count = field_count;
370
371 ret->fields = mnd_pecalloc(field_count + 1, sizeof(MYSQLND_FIELD), ret->persistent);
372 ret->zend_hash_keys = mnd_pecalloc(field_count, sizeof(struct mysqlnd_field_hash_key), ret->persistent);
373 if (!ret->fields || !ret->zend_hash_keys) {
374 break;
375 }
376 DBG_INF_FMT("meta=%p", ret);
377 DBG_RETURN(ret);
378 } while (0);
379 if (ret) {
380 ret->m->free_metadata(ret);
381 }
382 DBG_RETURN(NULL);
383 }
384
385
386
387
388 PHPAPI struct st_mysqlnd_res_meta_methods *
389 mysqlnd_result_metadata_get_methods()
390 {
391 return &mysqlnd_mysqlnd_res_meta_methods;
392 }
393
394
395
396
397 PHPAPI void **
398 _mysqlnd_plugin_get_plugin_result_metadata_data(const MYSQLND_RES_METADATA * meta, unsigned int plugin_id)
399 {
400 DBG_ENTER("_mysqlnd_plugin_get_plugin_result_metadata_data");
401 DBG_INF_FMT("plugin_id=%u", plugin_id);
402 if (!meta || plugin_id >= mysqlnd_plugin_count()) {
403 return NULL;
404 }
405 DBG_RETURN((void *)((char *)meta + sizeof(MYSQLND_RES_METADATA) + plugin_id * sizeof(void *)));
406 }
407
408
409
410
411
412
413
414
415
416