This source file includes following definitions.
- ps_fetch_from_1_to_8_bytes
- ps_fetch_null
- ps_fetch_int8
- ps_fetch_int16
- ps_fetch_int32
- ps_fetch_int64
- ps_fetch_float
- ps_fetch_double
- ps_fetch_time
- ps_fetch_date
- ps_fetch_datetime
- ps_fetch_string
- ps_fetch_bit
- _mysqlnd_init_ps_fetch_subsystem
- mysqlnd_stmt_copy_it
- mysqlnd_stmt_free_copies
- mysqlnd_stmt_execute_check_n_enlarge_buffer
- mysqlnd_stmt_execute_prepare_param_types
- mysqlnd_stmt_execute_store_types
- mysqlnd_stmt_execute_calculate_param_values_size
- mysqlnd_stmt_execute_store_param_values
- mysqlnd_stmt_execute_store_params
- mysqlnd_stmt_execute_generate_request
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_wireprotocol.h"
25 #include "mysqlnd_priv.h"
26 #include "mysqlnd_debug.h"
27 #include "ext/mysqlnd/mysql_float_to_double.h"
28
29 #define MYSQLND_SILENT
30
31
32 enum mysqlnd_timestamp_type
33 {
34 MYSQLND_TIMESTAMP_NONE= -2,
35 MYSQLND_TIMESTAMP_ERROR= -1,
36 MYSQLND_TIMESTAMP_DATE= 0,
37 MYSQLND_TIMESTAMP_DATETIME= 1,
38 MYSQLND_TIMESTAMP_TIME= 2
39 };
40
41
42 struct st_mysqlnd_time
43 {
44 unsigned int year, month, day, hour, minute, second;
45 zend_ulong second_part;
46 zend_bool neg;
47 enum mysqlnd_timestamp_type time_type;
48 };
49
50
51 struct st_mysqlnd_perm_bind mysqlnd_ps_fetch_functions[MYSQL_TYPE_LAST + 1];
52
53 #define MYSQLND_PS_SKIP_RESULT_W_LEN -1
54 #define MYSQLND_PS_SKIP_RESULT_STR -2
55
56
57 void
58 ps_fetch_from_1_to_8_bytes(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len,
59 zend_uchar ** row, unsigned int byte_count)
60 {
61 char tmp[22];
62 size_t tmp_len = 0;
63 zend_bool is_bit = field->type == MYSQL_TYPE_BIT;
64 DBG_ENTER("ps_fetch_from_1_to_8_bytes");
65 DBG_INF_FMT("zv=%p byte_count=%u", zv, byte_count);
66 if (field->flags & UNSIGNED_FLAG) {
67 uint64_t uval = 0;
68
69 switch (byte_count) {
70 case 8:uval = is_bit? (uint64_t) bit_uint8korr(*row):(uint64_t) uint8korr(*row);break;
71 case 7:uval = bit_uint7korr(*row);break;
72 case 6:uval = bit_uint6korr(*row);break;
73 case 5:uval = bit_uint5korr(*row);break;
74 case 4:uval = is_bit? (uint64_t) bit_uint4korr(*row):(uint64_t) uint4korr(*row);break;
75 case 3:uval = is_bit? (uint64_t) bit_uint3korr(*row):(uint64_t) uint3korr(*row);break;
76 case 2:uval = is_bit? (uint64_t) bit_uint2korr(*row):(uint64_t) uint2korr(*row);break;
77 case 1:uval = (uint64_t) uint1korr(*row);break;
78 }
79
80 #if SIZEOF_ZEND_LONG==4
81 if (uval > INT_MAX) {
82 DBG_INF("stringify");
83 tmp_len = sprintf((char *)&tmp, MYSQLND_LLU_SPEC, uval);
84 } else
85 #endif
86 {
87 if (byte_count < 8 || uval <= L64(9223372036854775807)) {
88 ZVAL_LONG(zv, (zend_long) uval);
89 } else {
90 DBG_INF("stringify");
91 tmp_len = sprintf((char *)&tmp, MYSQLND_LLU_SPEC, uval);
92 }
93 }
94 } else {
95
96 int64_t lval = 0;
97 switch (byte_count) {
98 case 8:lval = (int64_t) sint8korr(*row);break;
99
100
101
102
103 case 4:lval = (int64_t) sint4korr(*row);break;
104 case 3:lval = (int64_t) sint3korr(*row);break;
105 case 2:lval = (int64_t) sint2korr(*row);break;
106 case 1:lval = (int64_t) *(int8_t*)*row;break;
107 }
108
109 #if SIZEOF_ZEND_LONG==4
110 if ((L64(2147483647) < (int64_t) lval) || (L64(-2147483648) > (int64_t) lval)) {
111 DBG_INF("stringify");
112 tmp_len = sprintf((char *)&tmp, MYSQLND_LL_SPEC, lval);
113 } else
114 #endif
115 {
116 ZVAL_LONG(zv, (zend_long) lval);
117 }
118 }
119
120 if (tmp_len) {
121 ZVAL_STRINGL(zv, tmp, tmp_len);
122 }
123 (*row)+= byte_count;
124 DBG_VOID_RETURN;
125 }
126
127
128
129
130 static void
131 ps_fetch_null(zval *zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row)
132 {
133 ZVAL_NULL(zv);
134 }
135
136
137
138
139 static void
140 ps_fetch_int8(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row)
141 {
142 ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, 1);
143 }
144
145
146
147
148 static void
149 ps_fetch_int16(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row)
150 {
151 ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, 2);
152 }
153
154
155
156
157 static void
158 ps_fetch_int32(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row)
159 {
160 ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, 4);
161 }
162
163
164
165
166 static void
167 ps_fetch_int64(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row)
168 {
169 ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, 8);
170 }
171
172
173
174
175 static void
176 ps_fetch_float(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row)
177 {
178 float fval;
179 double dval;
180 DBG_ENTER("ps_fetch_float");
181 float4get(fval, *row);
182 (*row)+= 4;
183 DBG_INF_FMT("value=%f", fval);
184
185 #ifndef NOT_FIXED_DEC
186 # define NOT_FIXED_DEC 31
187 #endif
188
189 dval = mysql_float_to_double(fval, (field->decimals >= NOT_FIXED_DEC) ? -1 : field->decimals);
190
191 ZVAL_DOUBLE(zv, dval);
192 DBG_VOID_RETURN;
193 }
194
195
196
197
198 static void
199 ps_fetch_double(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row)
200 {
201 double value;
202 DBG_ENTER("ps_fetch_double");
203 float8get(value, *row);
204 ZVAL_DOUBLE(zv, value);
205 (*row)+= 8;
206 DBG_INF_FMT("value=%f", value);
207 DBG_VOID_RETURN;
208 }
209
210
211
212
213 static void
214 ps_fetch_time(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row)
215 {
216 struct st_mysqlnd_time t;
217 zend_ulong length;
218 char * value;
219 DBG_ENTER("ps_fetch_time");
220
221 if ((length = php_mysqlnd_net_field_length(row))) {
222 zend_uchar * to= *row;
223
224 t.time_type = MYSQLND_TIMESTAMP_TIME;
225 t.neg = (zend_bool) to[0];
226
227 t.day = (zend_ulong) sint4korr(to+1);
228 t.hour = (unsigned int) to[5];
229 t.minute = (unsigned int) to[6];
230 t.second = (unsigned int) to[7];
231 t.second_part = (length > 8) ? (zend_ulong) sint4korr(to+8) : 0;
232 t.year = t.month= 0;
233 if (t.day) {
234
235 t.hour += t.day*24;
236 t.day = 0;
237 }
238
239 (*row) += length;
240 } else {
241 memset(&t, 0, sizeof(t));
242 t.time_type = MYSQLND_TIMESTAMP_TIME;
243 }
244
245 length = mnd_sprintf(&value, 0, "%s%02u:%02u:%02u", (t.neg ? "-" : ""), t.hour, t.minute, t.second);
246
247 DBG_INF_FMT("%s", value);
248 ZVAL_STRINGL(zv, value, length);
249 mnd_sprintf_free(value);
250 DBG_VOID_RETURN;
251 }
252
253
254
255
256 static void
257 ps_fetch_date(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row)
258 {
259 struct st_mysqlnd_time t = {0};
260 zend_ulong length;
261 char * value;
262 DBG_ENTER("ps_fetch_date");
263
264 if ((length = php_mysqlnd_net_field_length(row))) {
265 zend_uchar *to= *row;
266
267 t.time_type= MYSQLND_TIMESTAMP_DATE;
268 t.neg= 0;
269
270 t.second_part = t.hour = t.minute = t.second = 0;
271
272 t.year = (unsigned int) sint2korr(to);
273 t.month = (unsigned int) to[2];
274 t.day = (unsigned int) to[3];
275
276 (*row)+= length;
277 } else {
278 memset(&t, 0, sizeof(t));
279 t.time_type = MYSQLND_TIMESTAMP_DATE;
280 }
281
282 length = mnd_sprintf(&value, 0, "%04u-%02u-%02u", t.year, t.month, t.day);
283
284 DBG_INF_FMT("%s", value);
285 ZVAL_STRINGL(zv, value, length);
286 mnd_sprintf_free(value);
287 DBG_VOID_RETURN;
288 }
289
290
291
292
293 static void
294 ps_fetch_datetime(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row)
295 {
296 struct st_mysqlnd_time t;
297 zend_ulong length;
298 char * value;
299 DBG_ENTER("ps_fetch_datetime");
300
301 if ((length = php_mysqlnd_net_field_length(row))) {
302 zend_uchar * to = *row;
303
304 t.time_type = MYSQLND_TIMESTAMP_DATETIME;
305 t.neg = 0;
306
307 t.year = (unsigned int) sint2korr(to);
308 t.month = (unsigned int) to[2];
309 t.day = (unsigned int) to[3];
310
311 if (length > 4) {
312 t.hour = (unsigned int) to[4];
313 t.minute = (unsigned int) to[5];
314 t.second = (unsigned int) to[6];
315 } else {
316 t.hour = t.minute = t.second= 0;
317 }
318 t.second_part = (length > 7) ? (zend_ulong) sint4korr(to+7) : 0;
319
320 (*row)+= length;
321 } else {
322 memset(&t, 0, sizeof(t));
323 t.time_type = MYSQLND_TIMESTAMP_DATETIME;
324 }
325
326 length = mnd_sprintf(&value, 0, "%04u-%02u-%02u %02u:%02u:%02u", t.year, t.month, t.day, t.hour, t.minute, t.second);
327
328 DBG_INF_FMT("%s", value);
329 ZVAL_STRINGL(zv, value, length);
330 mnd_sprintf_free(value);
331 DBG_VOID_RETURN;
332 }
333
334
335
336
337 static void
338 ps_fetch_string(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row)
339 {
340
341
342
343
344 const zend_ulong length = php_mysqlnd_net_field_length(row);
345 DBG_ENTER("ps_fetch_string");
346 DBG_INF_FMT("len = %lu", length);
347 DBG_INF("copying from the row buffer");
348 ZVAL_STRINGL(zv, (char *)*row, length);
349
350 (*row) += length;
351 DBG_VOID_RETURN;
352 }
353
354
355
356
357 static void
358 ps_fetch_bit(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row)
359 {
360 zend_ulong length = php_mysqlnd_net_field_length(row);
361 ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, length);
362 }
363
364
365
366
367 void _mysqlnd_init_ps_fetch_subsystem()
368 {
369 memset(mysqlnd_ps_fetch_functions, 0, sizeof(mysqlnd_ps_fetch_functions));
370 mysqlnd_ps_fetch_functions[MYSQL_TYPE_NULL].func = ps_fetch_null;
371 mysqlnd_ps_fetch_functions[MYSQL_TYPE_NULL].pack_len = 0;
372 mysqlnd_ps_fetch_functions[MYSQL_TYPE_NULL].php_type = IS_NULL;
373 mysqlnd_ps_fetch_functions[MYSQL_TYPE_NULL].can_ret_as_str_in_uni = TRUE;
374
375 mysqlnd_ps_fetch_functions[MYSQL_TYPE_TINY].func = ps_fetch_int8;
376 mysqlnd_ps_fetch_functions[MYSQL_TYPE_TINY].pack_len = 1;
377 mysqlnd_ps_fetch_functions[MYSQL_TYPE_TINY].php_type = IS_LONG;
378 mysqlnd_ps_fetch_functions[MYSQL_TYPE_TINY].can_ret_as_str_in_uni = TRUE;
379
380 mysqlnd_ps_fetch_functions[MYSQL_TYPE_SHORT].func = ps_fetch_int16;
381 mysqlnd_ps_fetch_functions[MYSQL_TYPE_SHORT].pack_len = 2;
382 mysqlnd_ps_fetch_functions[MYSQL_TYPE_SHORT].php_type = IS_LONG;
383 mysqlnd_ps_fetch_functions[MYSQL_TYPE_SHORT].can_ret_as_str_in_uni = TRUE;
384
385 mysqlnd_ps_fetch_functions[MYSQL_TYPE_YEAR].func = ps_fetch_int16;
386 mysqlnd_ps_fetch_functions[MYSQL_TYPE_YEAR].pack_len = 2;
387 mysqlnd_ps_fetch_functions[MYSQL_TYPE_YEAR].php_type = IS_LONG;
388 mysqlnd_ps_fetch_functions[MYSQL_TYPE_YEAR].can_ret_as_str_in_uni = TRUE;
389
390 mysqlnd_ps_fetch_functions[MYSQL_TYPE_INT24].func = ps_fetch_int32;
391 mysqlnd_ps_fetch_functions[MYSQL_TYPE_INT24].pack_len = 4;
392 mysqlnd_ps_fetch_functions[MYSQL_TYPE_INT24].php_type = IS_LONG;
393 mysqlnd_ps_fetch_functions[MYSQL_TYPE_INT24].can_ret_as_str_in_uni = TRUE;
394
395 mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONG].func = ps_fetch_int32;
396 mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONG].pack_len = 4;
397 mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONG].php_type = IS_LONG;
398 mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONG].can_ret_as_str_in_uni = TRUE;
399
400 mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONGLONG].func = ps_fetch_int64;
401 mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONGLONG].pack_len= 8;
402 mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONGLONG].php_type= IS_LONG;
403 mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONGLONG].can_ret_as_str_in_uni = TRUE;
404
405 mysqlnd_ps_fetch_functions[MYSQL_TYPE_FLOAT].func = ps_fetch_float;
406 mysqlnd_ps_fetch_functions[MYSQL_TYPE_FLOAT].pack_len = 4;
407 mysqlnd_ps_fetch_functions[MYSQL_TYPE_FLOAT].php_type = IS_DOUBLE;
408 mysqlnd_ps_fetch_functions[MYSQL_TYPE_FLOAT].can_ret_as_str_in_uni = TRUE;
409
410 mysqlnd_ps_fetch_functions[MYSQL_TYPE_DOUBLE].func = ps_fetch_double;
411 mysqlnd_ps_fetch_functions[MYSQL_TYPE_DOUBLE].pack_len = 8;
412 mysqlnd_ps_fetch_functions[MYSQL_TYPE_DOUBLE].php_type = IS_DOUBLE;
413 mysqlnd_ps_fetch_functions[MYSQL_TYPE_DOUBLE].can_ret_as_str_in_uni = TRUE;
414
415 mysqlnd_ps_fetch_functions[MYSQL_TYPE_TIME].func = ps_fetch_time;
416 mysqlnd_ps_fetch_functions[MYSQL_TYPE_TIME].pack_len = MYSQLND_PS_SKIP_RESULT_W_LEN;
417 mysqlnd_ps_fetch_functions[MYSQL_TYPE_TIME].php_type = IS_STRING;
418 mysqlnd_ps_fetch_functions[MYSQL_TYPE_TIME].can_ret_as_str_in_uni = TRUE;
419
420 mysqlnd_ps_fetch_functions[MYSQL_TYPE_DATE].func = ps_fetch_date;
421 mysqlnd_ps_fetch_functions[MYSQL_TYPE_DATE].pack_len = MYSQLND_PS_SKIP_RESULT_W_LEN;
422 mysqlnd_ps_fetch_functions[MYSQL_TYPE_DATE].php_type = IS_STRING;
423 mysqlnd_ps_fetch_functions[MYSQL_TYPE_DATE].can_ret_as_str_in_uni = TRUE;
424
425 mysqlnd_ps_fetch_functions[MYSQL_TYPE_NEWDATE].func = ps_fetch_string;
426 mysqlnd_ps_fetch_functions[MYSQL_TYPE_NEWDATE].pack_len = MYSQLND_PS_SKIP_RESULT_W_LEN;
427 mysqlnd_ps_fetch_functions[MYSQL_TYPE_NEWDATE].php_type = IS_STRING;
428 mysqlnd_ps_fetch_functions[MYSQL_TYPE_NEWDATE].can_ret_as_str_in_uni = TRUE;
429
430 mysqlnd_ps_fetch_functions[MYSQL_TYPE_DATETIME].func = ps_fetch_datetime;
431 mysqlnd_ps_fetch_functions[MYSQL_TYPE_DATETIME].pack_len= MYSQLND_PS_SKIP_RESULT_W_LEN;
432 mysqlnd_ps_fetch_functions[MYSQL_TYPE_DATETIME].php_type= IS_STRING;
433 mysqlnd_ps_fetch_functions[MYSQL_TYPE_DATETIME].can_ret_as_str_in_uni = TRUE;
434
435 mysqlnd_ps_fetch_functions[MYSQL_TYPE_TIMESTAMP].func = ps_fetch_datetime;
436 mysqlnd_ps_fetch_functions[MYSQL_TYPE_TIMESTAMP].pack_len= MYSQLND_PS_SKIP_RESULT_W_LEN;
437 mysqlnd_ps_fetch_functions[MYSQL_TYPE_TIMESTAMP].php_type= IS_STRING;
438 mysqlnd_ps_fetch_functions[MYSQL_TYPE_TIMESTAMP].can_ret_as_str_in_uni = TRUE;
439
440 mysqlnd_ps_fetch_functions[MYSQL_TYPE_JSON].func = ps_fetch_string;
441 mysqlnd_ps_fetch_functions[MYSQL_TYPE_JSON].pack_len= MYSQLND_PS_SKIP_RESULT_STR;
442 mysqlnd_ps_fetch_functions[MYSQL_TYPE_JSON].php_type = IS_STRING;
443 mysqlnd_ps_fetch_functions[MYSQL_TYPE_JSON].is_possibly_blob = TRUE;
444 mysqlnd_ps_fetch_functions[MYSQL_TYPE_JSON].can_ret_as_str_in_uni = TRUE;
445
446 mysqlnd_ps_fetch_functions[MYSQL_TYPE_TINY_BLOB].func = ps_fetch_string;
447 mysqlnd_ps_fetch_functions[MYSQL_TYPE_TINY_BLOB].pack_len= MYSQLND_PS_SKIP_RESULT_STR;
448 mysqlnd_ps_fetch_functions[MYSQL_TYPE_TINY_BLOB].php_type = IS_STRING;
449 mysqlnd_ps_fetch_functions[MYSQL_TYPE_TINY_BLOB].is_possibly_blob = TRUE;
450 mysqlnd_ps_fetch_functions[MYSQL_TYPE_TINY_BLOB].can_ret_as_str_in_uni = TRUE;
451
452 mysqlnd_ps_fetch_functions[MYSQL_TYPE_BLOB].func = ps_fetch_string;
453 mysqlnd_ps_fetch_functions[MYSQL_TYPE_BLOB].pack_len = MYSQLND_PS_SKIP_RESULT_STR;
454 mysqlnd_ps_fetch_functions[MYSQL_TYPE_BLOB].php_type = IS_STRING;
455 mysqlnd_ps_fetch_functions[MYSQL_TYPE_BLOB].is_possibly_blob = TRUE;
456 mysqlnd_ps_fetch_functions[MYSQL_TYPE_BLOB].can_ret_as_str_in_uni = TRUE;
457
458 mysqlnd_ps_fetch_functions[MYSQL_TYPE_MEDIUM_BLOB].func = ps_fetch_string;
459 mysqlnd_ps_fetch_functions[MYSQL_TYPE_MEDIUM_BLOB].pack_len = MYSQLND_PS_SKIP_RESULT_STR;
460 mysqlnd_ps_fetch_functions[MYSQL_TYPE_MEDIUM_BLOB].php_type = IS_STRING;
461 mysqlnd_ps_fetch_functions[MYSQL_TYPE_MEDIUM_BLOB].is_possibly_blob = TRUE;
462 mysqlnd_ps_fetch_functions[MYSQL_TYPE_MEDIUM_BLOB].can_ret_as_str_in_uni = TRUE;
463
464 mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONG_BLOB].func = ps_fetch_string;
465 mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONG_BLOB].pack_len = MYSQLND_PS_SKIP_RESULT_STR;
466 mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONG_BLOB].php_type = IS_STRING;
467 mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONG_BLOB].is_possibly_blob = TRUE;
468 mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONG_BLOB].can_ret_as_str_in_uni = TRUE;
469
470 mysqlnd_ps_fetch_functions[MYSQL_TYPE_BIT].func = ps_fetch_bit;
471 mysqlnd_ps_fetch_functions[MYSQL_TYPE_BIT].pack_len = 8;
472 mysqlnd_ps_fetch_functions[MYSQL_TYPE_BIT].php_type = IS_LONG;
473 mysqlnd_ps_fetch_functions[MYSQL_TYPE_BIT].can_ret_as_str_in_uni = TRUE;
474
475 mysqlnd_ps_fetch_functions[MYSQL_TYPE_VAR_STRING].func = ps_fetch_string;
476 mysqlnd_ps_fetch_functions[MYSQL_TYPE_VAR_STRING].pack_len = MYSQLND_PS_SKIP_RESULT_STR;
477 mysqlnd_ps_fetch_functions[MYSQL_TYPE_VAR_STRING].php_type = IS_STRING;
478 mysqlnd_ps_fetch_functions[MYSQL_TYPE_VAR_STRING].is_possibly_blob = TRUE;
479
480 mysqlnd_ps_fetch_functions[MYSQL_TYPE_VARCHAR].func = ps_fetch_string;
481 mysqlnd_ps_fetch_functions[MYSQL_TYPE_VARCHAR].pack_len = MYSQLND_PS_SKIP_RESULT_STR;
482 mysqlnd_ps_fetch_functions[MYSQL_TYPE_VARCHAR].php_type = IS_STRING;
483 mysqlnd_ps_fetch_functions[MYSQL_TYPE_VARCHAR].is_possibly_blob = TRUE;
484
485 mysqlnd_ps_fetch_functions[MYSQL_TYPE_STRING].func = ps_fetch_string;
486 mysqlnd_ps_fetch_functions[MYSQL_TYPE_STRING].pack_len = MYSQLND_PS_SKIP_RESULT_STR;
487 mysqlnd_ps_fetch_functions[MYSQL_TYPE_STRING].php_type = IS_STRING;
488 mysqlnd_ps_fetch_functions[MYSQL_TYPE_STRING].is_possibly_blob = TRUE;
489
490 mysqlnd_ps_fetch_functions[MYSQL_TYPE_DECIMAL].func = ps_fetch_string;
491 mysqlnd_ps_fetch_functions[MYSQL_TYPE_DECIMAL].pack_len = MYSQLND_PS_SKIP_RESULT_STR;
492 mysqlnd_ps_fetch_functions[MYSQL_TYPE_DECIMAL].php_type = IS_STRING;
493 mysqlnd_ps_fetch_functions[MYSQL_TYPE_DECIMAL].can_ret_as_str_in_uni = TRUE;
494
495 mysqlnd_ps_fetch_functions[MYSQL_TYPE_NEWDECIMAL].func = ps_fetch_string;
496 mysqlnd_ps_fetch_functions[MYSQL_TYPE_NEWDECIMAL].pack_len = MYSQLND_PS_SKIP_RESULT_STR;
497 mysqlnd_ps_fetch_functions[MYSQL_TYPE_NEWDECIMAL].php_type = IS_STRING;
498 mysqlnd_ps_fetch_functions[MYSQL_TYPE_NEWDECIMAL].can_ret_as_str_in_uni = TRUE;
499
500 mysqlnd_ps_fetch_functions[MYSQL_TYPE_ENUM].func = ps_fetch_string;
501 mysqlnd_ps_fetch_functions[MYSQL_TYPE_ENUM].pack_len = MYSQLND_PS_SKIP_RESULT_STR;
502 mysqlnd_ps_fetch_functions[MYSQL_TYPE_ENUM].php_type = IS_STRING;
503
504 mysqlnd_ps_fetch_functions[MYSQL_TYPE_SET].func = ps_fetch_string;
505 mysqlnd_ps_fetch_functions[MYSQL_TYPE_SET].pack_len = MYSQLND_PS_SKIP_RESULT_STR;
506 mysqlnd_ps_fetch_functions[MYSQL_TYPE_SET].php_type = IS_STRING;
507
508 mysqlnd_ps_fetch_functions[MYSQL_TYPE_GEOMETRY].func = ps_fetch_string;
509 mysqlnd_ps_fetch_functions[MYSQL_TYPE_GEOMETRY].pack_len= MYSQLND_PS_SKIP_RESULT_STR;
510 mysqlnd_ps_fetch_functions[MYSQL_TYPE_GEOMETRY].php_type= IS_STRING;
511 }
512
513
514
515
516 static enum_func_status
517 mysqlnd_stmt_copy_it(zval ** copies, zval * original, unsigned int param_count, unsigned int current)
518 {
519 if (!*copies) {
520 *copies = mnd_ecalloc(param_count, sizeof(zval));
521 }
522 if (*copies) {
523 ZVAL_COPY(&(*copies)[current], original);
524 return PASS;
525 }
526 return FAIL;
527 }
528
529
530
531
532 static void
533 mysqlnd_stmt_free_copies(MYSQLND_STMT_DATA * stmt, zval *copies)
534 {
535 if (copies) {
536 unsigned int i;
537 for (i = 0; i < stmt->param_count; i++) {
538 zval_ptr_dtor(&copies[i]);
539 }
540 mnd_efree(copies);
541 }
542 }
543
544
545
546
547 static enum_func_status
548 mysqlnd_stmt_execute_check_n_enlarge_buffer(zend_uchar **buf, zend_uchar **p, size_t * buf_len, zend_uchar * const provided_buffer, size_t needed_bytes)
549 {
550 const size_t overalloc = 5;
551 size_t left = (*buf_len - (*p - *buf));
552
553 if (left < (needed_bytes + overalloc)) {
554 size_t offset = *p - *buf;
555 zend_uchar *tmp_buf;
556 *buf_len = offset + needed_bytes + overalloc;
557 tmp_buf = mnd_emalloc(*buf_len);
558 if (!tmp_buf) {
559 return FAIL;
560 }
561 memcpy(tmp_buf, *buf, offset);
562 if (*buf != provided_buffer) {
563 mnd_efree(*buf);
564 }
565 *buf = tmp_buf;
566
567 *p = *buf + offset;
568 }
569 return PASS;
570 }
571
572
573
574
575 static enum_func_status
576 mysqlnd_stmt_execute_prepare_param_types(MYSQLND_STMT_DATA * stmt, zval ** copies_param, int * resend_types_next_time)
577 {
578 unsigned int i;
579 DBG_ENTER("mysqlnd_stmt_execute_prepare_param_types");
580 for (i = 0; i < stmt->param_count; i++) {
581 short current_type = stmt->param_bind[i].type;
582 zval *parameter = &stmt->param_bind[i].zv;
583
584 ZVAL_DEREF(parameter);
585 if (!Z_ISNULL_P(parameter) && (current_type == MYSQL_TYPE_LONG || current_type == MYSQL_TYPE_LONGLONG)) {
586
587 if (Z_TYPE_P(parameter) != IS_LONG &&
588 PASS != mysqlnd_stmt_copy_it(copies_param, parameter, stmt->param_count, i))
589 {
590 SET_OOM_ERROR(*stmt->error_info);
591 goto end;
592 }
593
594
595
596
597 if (Z_TYPE_P(parameter) != IS_LONG) {
598 zval *tmp_data = (*copies_param && !Z_ISUNDEF((*copies_param)[i]))? &(*copies_param)[i]: parameter;
599
600
601
602
603
604 zval tmp_data_copy;
605 ZVAL_COPY(&tmp_data_copy, tmp_data);
606 convert_to_double_ex(&tmp_data_copy);
607
608
609
610
611
612
613 if (Z_DVAL(tmp_data_copy) > ZEND_LONG_MAX || Z_DVAL(tmp_data_copy) < ZEND_LONG_MIN) {
614 stmt->send_types_to_server = *resend_types_next_time = 1;
615 convert_to_string_ex(tmp_data);
616 } else {
617 convert_to_long_ex(tmp_data);
618 }
619
620 zval_ptr_dtor(&tmp_data_copy);
621 }
622 }
623 }
624 DBG_RETURN(PASS);
625 end:
626 DBG_RETURN(FAIL);
627 }
628
629
630
631
632 static void
633 mysqlnd_stmt_execute_store_types(MYSQLND_STMT_DATA * stmt, zval * copies, zend_uchar ** p)
634 {
635 unsigned int i;
636 for (i = 0; i < stmt->param_count; i++) {
637 short current_type = stmt->param_bind[i].type;
638 zval *parameter = &stmt->param_bind[i].zv;
639
640 #if SIZEOF_ZEND_LONG==8
641 if (current_type == MYSQL_TYPE_LONG) {
642 current_type = MYSQL_TYPE_LONGLONG;
643 }
644 #endif
645 ZVAL_DEREF(parameter);
646 if (!Z_ISNULL_P(parameter) && (current_type == MYSQL_TYPE_LONG || current_type == MYSQL_TYPE_LONGLONG)) {
647
648
649
650
651 if (Z_TYPE_P(parameter) != IS_LONG) {
652 const zval *tmp_data = (copies && !Z_ISUNDEF(copies[i]))? &copies[i] : parameter;
653
654
655
656
657 if (Z_TYPE_P(tmp_data) == IS_STRING) {
658 current_type = MYSQL_TYPE_VAR_STRING;
659
660
661
662
663
664
665 }
666 }
667 }
668 int2store(*p, current_type);
669 *p+= 2;
670 }
671 }
672
673
674
675
676 static enum_func_status
677 mysqlnd_stmt_execute_calculate_param_values_size(MYSQLND_STMT_DATA * stmt, zval ** copies_param, size_t * data_size)
678 {
679 unsigned int i;
680 DBG_ENTER("mysqlnd_stmt_execute_calculate_param_values_size");
681 for (i = 0; i < stmt->param_count; i++) {
682 unsigned short is_longlong = 0;
683 unsigned int j;
684 zval *bind_var, *the_var = &stmt->param_bind[i].zv;
685
686 bind_var = the_var;
687 ZVAL_DEREF(the_var);
688 if ((stmt->param_bind[i].type != MYSQL_TYPE_LONG_BLOB && Z_TYPE_P(the_var) == IS_NULL)) {
689 continue;
690 }
691
692 if (Z_ISREF_P(bind_var)) {
693 for (j = i + 1; j < stmt->param_count; j++) {
694 if (Z_ISREF(stmt->param_bind[j].zv) && Z_REFVAL(stmt->param_bind[j].zv) == the_var) {
695
696 if (!*copies_param || Z_ISUNDEF((*copies_param)[i])) {
697 if (PASS != mysqlnd_stmt_copy_it(copies_param, the_var, stmt->param_count, i)) {
698 SET_OOM_ERROR(*stmt->error_info);
699 goto end;
700 }
701 }
702 break;
703 }
704 }
705 }
706
707 switch (stmt->param_bind[i].type) {
708 case MYSQL_TYPE_DOUBLE:
709 *data_size += 8;
710 if (Z_TYPE_P(the_var) != IS_DOUBLE) {
711 if (!*copies_param || Z_ISUNDEF((*copies_param)[i])) {
712 if (PASS != mysqlnd_stmt_copy_it(copies_param, the_var, stmt->param_count, i)) {
713 SET_OOM_ERROR(*stmt->error_info);
714 goto end;
715 }
716 }
717 }
718 break;
719 case MYSQL_TYPE_LONGLONG:
720 is_longlong = 4;
721
722 case MYSQL_TYPE_LONG:
723 {
724 zval *tmp_data = (*copies_param && !Z_ISUNDEF((*copies_param)[i]))? &(*copies_param)[i]: the_var;
725 if (Z_TYPE_P(tmp_data) == IS_STRING) {
726 goto use_string;
727 }
728 convert_to_long_ex(tmp_data);
729 }
730 *data_size += 4 + is_longlong;
731 break;
732 case MYSQL_TYPE_LONG_BLOB:
733 if (!(stmt->param_bind[i].flags & MYSQLND_PARAM_BIND_BLOB_USED)) {
734
735
736
737
738
739 (*data_size)++;
740 }
741 break;
742 case MYSQL_TYPE_VAR_STRING:
743 use_string:
744 *data_size += 8;
745 if (Z_TYPE_P(the_var) != IS_STRING) {
746 if (!*copies_param || Z_ISUNDEF((*copies_param)[i])) {
747 if (PASS != mysqlnd_stmt_copy_it(copies_param, the_var, stmt->param_count, i)) {
748 SET_OOM_ERROR(*stmt->error_info);
749 goto end;
750 }
751 }
752 the_var = &((*copies_param)[i]);
753 }
754 convert_to_string_ex(the_var);
755 *data_size += Z_STRLEN_P(the_var);
756 break;
757 }
758 }
759 DBG_RETURN(PASS);
760 end:
761 DBG_RETURN(FAIL);
762 }
763
764
765
766
767 static void
768 mysqlnd_stmt_execute_store_param_values(MYSQLND_STMT_DATA * stmt, zval * copies, zend_uchar * buf, zend_uchar ** p, size_t null_byte_offset)
769 {
770 unsigned int i;
771 for (i = 0; i < stmt->param_count; i++) {
772 zval *data, *parameter = &stmt->param_bind[i].zv;
773
774 ZVAL_DEREF(parameter);
775 data = (copies && !Z_ISUNDEF(copies[i]))? &copies[i]: parameter;
776
777 if (!Z_ISUNDEF_P(parameter) && Z_TYPE_P(data) == IS_NULL) {
778 (buf + null_byte_offset)[i/8] |= (zend_uchar) (1 << (i & 7));
779 } else {
780 switch (stmt->param_bind[i].type) {
781 case MYSQL_TYPE_DOUBLE:
782 convert_to_double_ex(data);
783 float8store(*p, Z_DVAL_P(data));
784 (*p) += 8;
785 break;
786 case MYSQL_TYPE_LONGLONG:
787 if (Z_TYPE_P(data) == IS_STRING) {
788 goto send_string;
789 }
790
791 int8store(*p, Z_LVAL_P(data));
792 (*p) += 8;
793 break;
794 case MYSQL_TYPE_LONG:
795 if (Z_TYPE_P(data) == IS_STRING) {
796 goto send_string;
797 }
798
799 int4store(*p, Z_LVAL_P(data));
800 (*p) += 4;
801 break;
802 case MYSQL_TYPE_LONG_BLOB:
803 if (stmt->param_bind[i].flags & MYSQLND_PARAM_BIND_BLOB_USED) {
804 stmt->param_bind[i].flags &= ~MYSQLND_PARAM_BIND_BLOB_USED;
805 } else {
806
807 *p = php_mysqlnd_net_store_length(*p, 0);
808 }
809 break;
810 case MYSQL_TYPE_VAR_STRING:
811 send_string:
812 {
813 size_t len = Z_STRLEN_P(data);
814
815 *p = php_mysqlnd_net_store_length(*p, len);
816 memcpy(*p, Z_STRVAL_P(data), len);
817 (*p) += len;
818 }
819 break;
820 default:
821
822 (buf + null_byte_offset)[i/8] |= (zend_uchar) (1 << (i & 7));
823 break;
824 }
825 }
826 }
827 }
828
829
830
831
832 static enum_func_status
833 mysqlnd_stmt_execute_store_params(MYSQLND_STMT * s, zend_uchar **buf, zend_uchar **p, size_t *buf_len )
834 {
835 MYSQLND_STMT_DATA * stmt = s->data;
836 zend_uchar * provided_buffer = *buf;
837 size_t data_size = 0;
838 zval *copies = NULL;
839 enum_func_status ret = FAIL;
840 int resend_types_next_time = 0;
841 size_t null_byte_offset;
842
843 DBG_ENTER("mysqlnd_stmt_execute_store_params");
844
845 {
846 unsigned int null_count = (stmt->param_count + 7) / 8;
847 if (FAIL == mysqlnd_stmt_execute_check_n_enlarge_buffer(buf, p, buf_len, provided_buffer, null_count)) {
848 SET_OOM_ERROR(*stmt->error_info);
849 goto end;
850 }
851
852 null_byte_offset = *p - *buf;
853 memset(*p, 0, null_count);
854 *p += null_count;
855 }
856
857
858
859
860
861
862
863
864
865 if (FAIL == mysqlnd_stmt_execute_prepare_param_types(stmt, &copies, &resend_types_next_time)) {
866 goto end;
867 }
868
869 int1store(*p, stmt->send_types_to_server);
870 (*p)++;
871
872 if (stmt->send_types_to_server) {
873 if (FAIL == mysqlnd_stmt_execute_check_n_enlarge_buffer(buf, p, buf_len, provided_buffer, stmt->param_count * 2)) {
874 SET_OOM_ERROR(*stmt->error_info);
875 goto end;
876 }
877 mysqlnd_stmt_execute_store_types(stmt, copies, p);
878 }
879
880 stmt->send_types_to_server = resend_types_next_time;
881
882
883
884 if (FAIL == mysqlnd_stmt_execute_calculate_param_values_size(stmt, &copies, &data_size)) {
885 goto end;
886 }
887
888
889 if (FAIL == mysqlnd_stmt_execute_check_n_enlarge_buffer(buf, p, buf_len, provided_buffer, data_size)) {
890 SET_OOM_ERROR(*stmt->error_info);
891 goto end;
892 }
893
894
895 mysqlnd_stmt_execute_store_param_values(stmt, copies, *buf, p, null_byte_offset);
896
897 ret = PASS;
898 end:
899 mysqlnd_stmt_free_copies(stmt, copies);
900
901 DBG_INF_FMT("ret=%s", ret == PASS? "PASS":"FAIL");
902 DBG_RETURN(ret);
903 }
904
905
906
907
908 enum_func_status
909 mysqlnd_stmt_execute_generate_request(MYSQLND_STMT * const s, zend_uchar ** request, size_t *request_len, zend_bool * free_buffer)
910 {
911 MYSQLND_STMT_DATA * stmt = s->data;
912 zend_uchar *p = stmt->execute_cmd_buffer.buffer,
913 *cmd_buffer = stmt->execute_cmd_buffer.buffer;
914 size_t cmd_buffer_length = stmt->execute_cmd_buffer.length;
915 enum_func_status ret;
916
917 DBG_ENTER("mysqlnd_stmt_execute_generate_request");
918
919 int4store(p, stmt->stmt_id);
920 p += 4;
921
922
923 int1store(p, (zend_uchar) stmt->flags);
924 p++;
925
926
927 int4store(p, 0);
928
929 int1store(p, 1);
930 p+= 4;
931
932 ret = mysqlnd_stmt_execute_store_params(s, &cmd_buffer, &p, &cmd_buffer_length);
933
934 *free_buffer = (cmd_buffer != stmt->execute_cmd_buffer.buffer);
935 *request_len = (p - cmd_buffer);
936 *request = cmd_buffer;
937 DBG_INF_FMT("ret=%s", ret == PASS? "PASS":"FAIL");
938 DBG_RETURN(ret);
939 }
940
941
942
943
944
945
946
947
948
949