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 unsigned long 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 TSRMLS_DC)
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_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, (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_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, (long) lval);
117 }
118 }
119
120 if (tmp_len) {
121 ZVAL_STRINGL(zv, tmp, tmp_len, 1);
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 TSRMLS_DC)
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 TSRMLS_DC)
141 {
142 ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, 1 TSRMLS_CC);
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 TSRMLS_DC)
150 {
151 ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, 2 TSRMLS_CC);
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 TSRMLS_DC)
159 {
160 ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, 4 TSRMLS_CC);
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 TSRMLS_DC)
168 {
169 ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, 8 TSRMLS_CC);
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 TSRMLS_DC)
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 TSRMLS_DC)
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 TSRMLS_DC)
215 {
216 struct st_mysqlnd_time t;
217 unsigned long 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 = (unsigned long) 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) ? (unsigned long) 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, 1);
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 TSRMLS_DC)
258 {
259 struct st_mysqlnd_time t = {0};
260 unsigned long 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, 1);
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 TSRMLS_DC)
295 {
296 struct st_mysqlnd_time t;
297 unsigned long 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) ? (unsigned long) 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, 1);
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 TSRMLS_DC)
339 {
340
341
342
343
344 const unsigned long 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, 1);
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 TSRMLS_DC)
359 {
360 unsigned long length = php_mysqlnd_net_field_length(row);
361 ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, length TSRMLS_CC);
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 TSRMLS_DC)
518 {
519 if (!*copies) {
520 *copies = mnd_ecalloc(param_count, sizeof(zval *));
521 }
522 if (*copies) {
523 MAKE_STD_ZVAL((*copies)[current]);
524 *(*copies)[current] = *original;
525 Z_SET_REFCOUNT_P((*copies)[current], 1);
526 zval_copy_ctor((*copies)[current]);
527 return PASS;
528 }
529 return FAIL;
530 }
531
532
533
534
535 static void
536 mysqlnd_stmt_free_copies(MYSQLND_STMT_DATA * stmt, zval ** copies TSRMLS_DC)
537 {
538 if (copies) {
539 unsigned int i;
540 for (i = 0; i < stmt->param_count; i++) {
541 if (copies[i]) {
542 zval_ptr_dtor(&copies[i]);
543 }
544 }
545 mnd_efree(copies);
546 }
547 }
548
549
550
551
552 static enum_func_status
553 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 TSRMLS_DC)
554 {
555 const size_t overalloc = 5;
556 size_t left = (*buf_len - (*p - *buf));
557
558 if (left < (needed_bytes + overalloc)) {
559 size_t offset = *p - *buf;
560 zend_uchar *tmp_buf;
561 *buf_len = offset + needed_bytes + overalloc;
562 tmp_buf = mnd_emalloc(*buf_len);
563 if (!tmp_buf) {
564 return FAIL;
565 }
566 memcpy(tmp_buf, *buf, offset);
567 if (*buf != provided_buffer) {
568 mnd_efree(*buf);
569 }
570 *buf = tmp_buf;
571
572 *p = *buf + offset;
573 }
574 return PASS;
575 }
576
577
578
579
580 static enum_func_status
581 mysqlnd_stmt_execute_prepare_param_types(MYSQLND_STMT_DATA * stmt, zval *** copies_param, int * resend_types_next_time TSRMLS_DC)
582 {
583 unsigned int i;
584 DBG_ENTER("mysqlnd_stmt_execute_prepare_param_types");
585 for (i = 0; i < stmt->param_count; i++) {
586 short current_type = stmt->param_bind[i].type;
587
588 if (Z_TYPE_P(stmt->param_bind[i].zv) != IS_NULL && (current_type == MYSQL_TYPE_LONG || current_type == MYSQL_TYPE_LONGLONG)) {
589 zval ** copies;
590
591 if (Z_TYPE_P(stmt->param_bind[i].zv) != IS_LONG &&
592 PASS != mysqlnd_stmt_copy_it(copies_param, stmt->param_bind[i].zv, stmt->param_count, i TSRMLS_CC))
593 {
594 SET_OOM_ERROR(*stmt->error_info);
595 goto end;
596 }
597 copies = *copies_param;
598
599
600
601
602 if (Z_TYPE_P(stmt->param_bind[i].zv) != IS_LONG) {
603 zval *tmp_data = (copies && copies[i])? copies[i]: stmt->param_bind[i].zv;
604
605
606
607
608
609 zval *tmp_data_copy;
610 MAKE_STD_ZVAL(tmp_data_copy);
611 *tmp_data_copy = *tmp_data;
612 Z_SET_REFCOUNT_P(tmp_data_copy, 1);
613 zval_copy_ctor(tmp_data_copy);
614 convert_to_double_ex(&tmp_data_copy);
615
616
617
618
619
620
621 if (Z_DVAL_P(tmp_data_copy) > LONG_MAX || Z_DVAL_P(tmp_data_copy) < LONG_MIN) {
622 stmt->send_types_to_server = *resend_types_next_time = 1;
623 convert_to_string_ex(&tmp_data);
624 } else {
625 convert_to_long_ex(&tmp_data);
626 }
627
628 zval_ptr_dtor(&tmp_data_copy);
629 }
630 }
631 }
632 DBG_RETURN(PASS);
633 end:
634 DBG_RETURN(FAIL);
635 }
636
637
638
639
640 static void
641 mysqlnd_stmt_execute_store_types(MYSQLND_STMT_DATA * stmt, zval ** copies, zend_uchar ** p)
642 {
643 unsigned int i;
644 for (i = 0; i < stmt->param_count; i++) {
645 short current_type = stmt->param_bind[i].type;
646
647 #if SIZEOF_LONG==8
648 if (current_type == MYSQL_TYPE_LONG) {
649 current_type = MYSQL_TYPE_LONGLONG;
650 }
651 #endif
652 if (Z_TYPE_P(stmt->param_bind[i].zv) != IS_NULL && (current_type == MYSQL_TYPE_LONG || current_type == MYSQL_TYPE_LONGLONG)) {
653
654
655
656
657 if (Z_TYPE_P(stmt->param_bind[i].zv) != IS_LONG) {
658 const zval *tmp_data = (copies && copies[i])? copies[i]: stmt->param_bind[i].zv;
659
660
661
662
663 if (Z_TYPE_P(tmp_data) == IS_STRING) {
664 current_type = MYSQL_TYPE_VAR_STRING;
665
666
667
668
669
670
671 }
672 }
673 }
674 int2store(*p, current_type);
675 *p+= 2;
676 }
677 }
678
679
680
681
682 static enum_func_status
683 mysqlnd_stmt_execute_calculate_param_values_size(MYSQLND_STMT_DATA * stmt, zval *** copies_param, size_t * data_size TSRMLS_DC)
684 {
685 unsigned int i;
686 DBG_ENTER("mysqlnd_stmt_execute_calculate_param_values_size");
687 for (i = 0; i < stmt->param_count; i++) {
688 unsigned short is_longlong = 0;
689 unsigned int j;
690 zval *the_var = stmt->param_bind[i].zv;
691
692 if (!the_var || (stmt->param_bind[i].type != MYSQL_TYPE_LONG_BLOB && Z_TYPE_P(the_var) == IS_NULL)) {
693 continue;
694 }
695 for (j = i + 1; j < stmt->param_count; j++) {
696 if (stmt->param_bind[j].zv == the_var) {
697
698 if (!*copies_param || !(*copies_param)[i]) {
699 if (PASS != mysqlnd_stmt_copy_it(copies_param, the_var, stmt->param_count, i TSRMLS_CC)) {
700 SET_OOM_ERROR(*stmt->error_info);
701 goto end;
702 }
703 }
704 break;
705 }
706 }
707
708 switch (stmt->param_bind[i].type) {
709 case MYSQL_TYPE_DOUBLE:
710 *data_size += 8;
711 if (Z_TYPE_P(the_var) != IS_DOUBLE) {
712 if (!*copies_param || !(*copies_param)[i]) {
713 if (PASS != mysqlnd_stmt_copy_it(copies_param, the_var, stmt->param_count, i TSRMLS_CC)) {
714 SET_OOM_ERROR(*stmt->error_info);
715 goto end;
716 }
717 }
718 }
719 break;
720 case MYSQL_TYPE_LONGLONG:
721 is_longlong = 4;
722
723 case MYSQL_TYPE_LONG:
724 {
725 zval *tmp_data = (*copies_param && (*copies_param)[i])? (*copies_param)[i]: stmt->param_bind[i].zv;
726 if (Z_TYPE_P(tmp_data) == IS_STRING) {
727 goto use_string;
728 }
729 convert_to_long_ex(&tmp_data);
730 }
731 *data_size += 4 + is_longlong;
732 break;
733 case MYSQL_TYPE_LONG_BLOB:
734 if (!(stmt->param_bind[i].flags & MYSQLND_PARAM_BIND_BLOB_USED)) {
735
736
737
738
739
740 (*data_size)++;
741 }
742 break;
743 case MYSQL_TYPE_VAR_STRING:
744 use_string:
745 *data_size += 8;
746 if (Z_TYPE_P(the_var) != IS_STRING) {
747 if (!*copies_param || !(*copies_param)[i]) {
748 if (PASS != mysqlnd_stmt_copy_it(copies_param, the_var, stmt->param_count, i TSRMLS_CC)) {
749 SET_OOM_ERROR(*stmt->error_info);
750 goto end;
751 }
752 }
753 the_var = (*copies_param)[i];
754 }
755 convert_to_string_ex(&the_var);
756 *data_size += Z_STRLEN_P(the_var);
757 break;
758 }
759 }
760 DBG_RETURN(PASS);
761 end:
762 DBG_RETURN(FAIL);
763 }
764
765
766
767
768 static void
769 mysqlnd_stmt_execute_store_param_values(MYSQLND_STMT_DATA * stmt, zval ** copies, zend_uchar * buf, zend_uchar ** p, size_t null_byte_offset)
770 {
771 unsigned int i;
772 for (i = 0; i < stmt->param_count; i++) {
773 zval * data = (copies && copies[i])? copies[i]: stmt->param_bind[i].zv;
774
775 if (stmt->param_bind[i].zv && Z_TYPE_P(data) == IS_NULL) {
776 (buf + null_byte_offset)[i/8] |= (zend_uchar) (1 << (i & 7));
777 } else {
778 switch (stmt->param_bind[i].type) {
779 case MYSQL_TYPE_DOUBLE:
780 convert_to_double_ex(&data);
781 float8store(*p, Z_DVAL_P(data));
782 (*p) += 8;
783 break;
784 case MYSQL_TYPE_LONGLONG:
785 if (Z_TYPE_P(data) == IS_STRING) {
786 goto send_string;
787 }
788
789 int8store(*p, Z_LVAL_P(data));
790 (*p) += 8;
791 break;
792 case MYSQL_TYPE_LONG:
793 if (Z_TYPE_P(data) == IS_STRING) {
794 goto send_string;
795 }
796
797 int4store(*p, Z_LVAL_P(data));
798 (*p) += 4;
799 break;
800 case MYSQL_TYPE_LONG_BLOB:
801 if (stmt->param_bind[i].flags & MYSQLND_PARAM_BIND_BLOB_USED) {
802 stmt->param_bind[i].flags &= ~MYSQLND_PARAM_BIND_BLOB_USED;
803 } else {
804
805 *p = php_mysqlnd_net_store_length(*p, 0);
806 }
807 break;
808 case MYSQL_TYPE_VAR_STRING:
809 send_string:
810 {
811 size_t len = Z_STRLEN_P(data);
812
813 *p = php_mysqlnd_net_store_length(*p, len);
814 memcpy(*p, Z_STRVAL_P(data), len);
815 (*p) += len;
816 }
817 break;
818 default:
819
820 (buf + null_byte_offset)[i/8] |= (zend_uchar) (1 << (i & 7));
821 break;
822 }
823 }
824 }
825 }
826
827
828
829
830 static enum_func_status
831 mysqlnd_stmt_execute_store_params(MYSQLND_STMT * s, zend_uchar **buf, zend_uchar **p, size_t *buf_len TSRMLS_DC)
832 {
833 MYSQLND_STMT_DATA * stmt = s->data;
834 unsigned int i = 0;
835 zend_uchar * provided_buffer = *buf;
836 size_t data_size = 0;
837 zval **copies = NULL;
838 enum_func_status ret = FAIL;
839 int resend_types_next_time = 0;
840 size_t null_byte_offset;
841
842 DBG_ENTER("mysqlnd_stmt_execute_store_params");
843
844 {
845 unsigned int null_count = (stmt->param_count + 7) / 8;
846 if (FAIL == mysqlnd_stmt_execute_check_n_enlarge_buffer(buf, p, buf_len, provided_buffer, null_count TSRMLS_CC)) {
847 SET_OOM_ERROR(*stmt->error_info);
848 goto end;
849 }
850
851 null_byte_offset = *p - *buf;
852 memset(*p, 0, null_count);
853 *p += null_count;
854 }
855
856
857
858
859
860
861
862
863
864 if (FAIL == mysqlnd_stmt_execute_prepare_param_types(stmt, &copies, &resend_types_next_time TSRMLS_CC)) {
865 goto end;
866 }
867
868 int1store(*p, stmt->send_types_to_server);
869 (*p)++;
870
871 if (stmt->send_types_to_server) {
872 if (FAIL == mysqlnd_stmt_execute_check_n_enlarge_buffer(buf, p, buf_len, provided_buffer, stmt->param_count * 2 TSRMLS_CC)) {
873 SET_OOM_ERROR(*stmt->error_info);
874 goto end;
875 }
876 mysqlnd_stmt_execute_store_types(stmt, copies, p);
877 }
878
879 stmt->send_types_to_server = resend_types_next_time;
880
881
882
883 if (FAIL == mysqlnd_stmt_execute_calculate_param_values_size(stmt, &copies, &data_size TSRMLS_CC)) {
884 goto end;
885 }
886
887
888 if (FAIL == mysqlnd_stmt_execute_check_n_enlarge_buffer(buf, p, buf_len, provided_buffer, data_size TSRMLS_CC)) {
889 SET_OOM_ERROR(*stmt->error_info);
890 goto end;
891 }
892
893
894 mysqlnd_stmt_execute_store_param_values(stmt, copies, *buf, p, null_byte_offset);
895
896 ret = PASS;
897 end:
898 mysqlnd_stmt_free_copies(stmt, copies TSRMLS_CC);
899
900 DBG_INF_FMT("ret=%s", ret == PASS? "PASS":"FAIL");
901 DBG_RETURN(ret);
902 }
903
904
905
906
907 enum_func_status
908 mysqlnd_stmt_execute_generate_request(MYSQLND_STMT * const s, zend_uchar ** request, size_t *request_len, zend_bool * free_buffer TSRMLS_DC)
909 {
910 MYSQLND_STMT_DATA * stmt = s->data;
911 zend_uchar *p = stmt->execute_cmd_buffer.buffer,
912 *cmd_buffer = stmt->execute_cmd_buffer.buffer;
913 size_t cmd_buffer_length = stmt->execute_cmd_buffer.length;
914 enum_func_status ret;
915
916 DBG_ENTER("mysqlnd_stmt_execute_generate_request");
917
918 int4store(p, stmt->stmt_id);
919 p += 4;
920
921
922 int1store(p, (zend_uchar) stmt->flags);
923 p++;
924
925
926 int4store(p, 0);
927
928 int1store(p, 1);
929 p+= 4;
930
931 ret = mysqlnd_stmt_execute_store_params(s, &cmd_buffer, &p, &cmd_buffer_length TSRMLS_CC);
932
933 *free_buffer = (cmd_buffer != stmt->execute_cmd_buffer.buffer);
934 *request_len = (p - cmd_buffer);
935 *request = cmd_buffer;
936 DBG_INF_FMT("ret=%s", ret == PASS? "PASS":"FAIL");
937 DBG_RETURN(ret);
938 }
939
940
941
942
943
944
945
946
947
948