@@ -476,6 +476,146 @@ PHP_FUNCTION(mysqli_stmt_execute)
476
476
}
477
477
/* }}} */
478
478
479
+ void close_stmt_and_copy_errors (MY_STMT * stmt , MY_MYSQL * mysql )
480
+ {
481
+ /* mysql_stmt_close() clears errors, so we have to store them temporarily */
482
+ MYSQLND_ERROR_INFO error_info = * stmt -> stmt -> data -> error_info ;
483
+ stmt -> stmt -> data -> error_info -> error_list .head = NULL ;
484
+ stmt -> stmt -> data -> error_info -> error_list .tail = NULL ;
485
+ stmt -> stmt -> data -> error_info -> error_list .count = 0 ;
486
+
487
+ /* we also remember affected_rows which gets cleared too */
488
+ uint64_t affected_rows = mysql -> mysql -> data -> upsert_status -> affected_rows ;
489
+
490
+ mysqli_stmt_close (stmt -> stmt , false);
491
+ stmt -> stmt = NULL ;
492
+ php_clear_stmt_bind (stmt );
493
+
494
+ /* restore error messages, but into the mysql object */
495
+ zend_llist_clean (& mysql -> mysql -> data -> error_info -> error_list );
496
+ * mysql -> mysql -> data -> error_info = error_info ;
497
+ mysql -> mysql -> data -> upsert_status -> affected_rows = affected_rows ;
498
+ }
499
+
500
+ PHP_FUNCTION (mysqli_execute_query )
501
+ {
502
+ MY_MYSQL * mysql ;
503
+ MY_STMT * stmt ;
504
+ char * query = NULL ;
505
+ size_t query_len ;
506
+ zval * mysql_link ;
507
+ HashTable * input_params = NULL ;
508
+ MYSQL_RES * result ;
509
+ MYSQLI_RESOURCE * mysqli_resource ;
510
+
511
+ if (zend_parse_method_parameters (ZEND_NUM_ARGS (), getThis (), "Os|h!" , & mysql_link , mysqli_link_class_entry , & query , & query_len , & input_params ) == FAILURE ) {
512
+ RETURN_THROWS ();
513
+ }
514
+ MYSQLI_FETCH_RESOURCE_CONN (mysql , mysql_link , MYSQLI_STATUS_VALID );
515
+
516
+ stmt = (MY_STMT * )ecalloc (1 ,sizeof (MY_STMT ));
517
+
518
+ if (!(stmt -> stmt = mysql_stmt_init (mysql -> mysql ))) {
519
+ MYSQLI_REPORT_MYSQL_ERROR (mysql -> mysql );
520
+ efree (stmt );
521
+ RETURN_FALSE ;
522
+ }
523
+
524
+ if (FAIL == mysql_stmt_prepare (stmt -> stmt , query , query_len )) {
525
+ MYSQLI_REPORT_STMT_ERROR (stmt -> stmt );
526
+
527
+ close_stmt_and_copy_errors (stmt , mysql );
528
+ RETURN_FALSE ;
529
+ }
530
+
531
+ /* The bit below, which is copied from mysqli_prepare, is needed for bad index exceptions */
532
+ /* don't initialize stmt->query with NULL, we ecalloc()-ed the memory */
533
+ /* Get performance boost if reporting is switched off */
534
+ if (query_len && (MyG (report_mode ) & MYSQLI_REPORT_INDEX )) {
535
+ stmt -> query = estrdup (query );
536
+ }
537
+
538
+ // bind-in-execute
539
+ // It's very similar to the mysqli_stmt::execute, but it uses different error handling
540
+ if (input_params ) {
541
+ zval * tmp ;
542
+ unsigned int index ;
543
+ unsigned int hash_num_elements ;
544
+ unsigned int param_count ;
545
+ MYSQLND_PARAM_BIND * params ;
546
+
547
+ if (!zend_array_is_list (input_params )) {
548
+ mysqli_stmt_close (stmt -> stmt , false);
549
+ stmt -> stmt = NULL ;
550
+ efree (stmt );
551
+ zend_argument_value_error (ERROR_ARG_POS (3 ), "must be a list array" );
552
+ RETURN_THROWS ();
553
+ }
554
+
555
+ hash_num_elements = zend_hash_num_elements (input_params );
556
+ param_count = mysql_stmt_param_count (stmt -> stmt );
557
+ if (hash_num_elements != param_count ) {
558
+ mysqli_stmt_close (stmt -> stmt , false);
559
+ stmt -> stmt = NULL ;
560
+ efree (stmt );
561
+ zend_argument_value_error (ERROR_ARG_POS (3 ), "must consist of exactly %d elements, %d present" , param_count , hash_num_elements );
562
+ RETURN_THROWS ();
563
+ }
564
+
565
+ params = mysqlnd_stmt_alloc_param_bind (stmt -> stmt );
566
+ ZEND_ASSERT (params );
567
+
568
+ index = 0 ;
569
+ ZEND_HASH_FOREACH_VAL (input_params , tmp ) {
570
+ ZVAL_COPY_VALUE (& params [index ].zv , tmp );
571
+ params [index ].type = MYSQL_TYPE_VAR_STRING ;
572
+ index ++ ;
573
+ } ZEND_HASH_FOREACH_END ();
574
+
575
+ if (mysqlnd_stmt_bind_param (stmt -> stmt , params )) {
576
+ close_stmt_and_copy_errors (stmt , mysql );
577
+ RETURN_FALSE ;
578
+ }
579
+
580
+ }
581
+
582
+ if (mysql_stmt_execute (stmt -> stmt )) {
583
+ MYSQLI_REPORT_STMT_ERROR (stmt -> stmt );
584
+
585
+ if (MyG (report_mode ) & MYSQLI_REPORT_INDEX ) {
586
+ php_mysqli_report_index (stmt -> query , mysqli_stmt_server_status (stmt -> stmt ));
587
+ }
588
+
589
+ close_stmt_and_copy_errors (stmt , mysql );
590
+ RETURN_FALSE ;
591
+ }
592
+
593
+ if (!mysql_stmt_field_count (stmt -> stmt )) {
594
+ /* no result set - not a SELECT */
595
+ close_stmt_and_copy_errors (stmt , mysql );
596
+ RETURN_TRUE ;
597
+ }
598
+
599
+ if (MyG (report_mode ) & MYSQLI_REPORT_INDEX ) {
600
+ php_mysqli_report_index (stmt -> query , mysqli_stmt_server_status (stmt -> stmt ));
601
+ }
602
+
603
+ /* get result */
604
+ if (!(result = mysqlnd_stmt_get_result (stmt -> stmt ))) {
605
+ MYSQLI_REPORT_STMT_ERROR (stmt -> stmt );
606
+
607
+ close_stmt_and_copy_errors (stmt , mysql );
608
+ RETURN_FALSE ;
609
+ }
610
+
611
+ mysqli_resource = (MYSQLI_RESOURCE * )ecalloc (1 , sizeof (MYSQLI_RESOURCE ));
612
+ mysqli_resource -> ptr = (void * )result ;
613
+ mysqli_resource -> status = MYSQLI_STATUS_VALID ;
614
+ MYSQLI_RETVAL_RESOURCE (mysqli_resource , mysqli_result_class_entry );
615
+
616
+ close_stmt_and_copy_errors (stmt , mysql );
617
+ }
618
+
479
619
/* {{{ mixed mysqli_stmt_fetch_mysqlnd */
480
620
void mysqli_stmt_fetch_mysqlnd (INTERNAL_FUNCTION_PARAMETERS )
481
621
{
@@ -1188,9 +1328,7 @@ PHP_FUNCTION(mysqli_prepare)
1188
1328
/* don't initialize stmt->query with NULL, we ecalloc()-ed the memory */
1189
1329
/* Get performance boost if reporting is switched off */
1190
1330
if (stmt -> stmt && query_len && (MyG (report_mode ) & MYSQLI_REPORT_INDEX )) {
1191
- stmt -> query = (char * )emalloc (query_len + 1 );
1192
- memcpy (stmt -> query , query , query_len );
1193
- stmt -> query [query_len ] = '\0' ;
1331
+ stmt -> query = estrdup (query );
1194
1332
}
1195
1333
1196
1334
/* don't join to the previous if because it won't work if mysql_stmt_prepare_fails */
0 commit comments