summaryrefslogtreecommitdiff
path: root/ext/mysqli/tests
diff options
context:
space:
mode:
Diffstat (limited to 'ext/mysqli/tests')
-rw-r--r--ext/mysqli/tests/001.phpt63
-rw-r--r--ext/mysqli/tests/002.phpt85
-rw-r--r--ext/mysqli/tests/003.phpt103
-rw-r--r--ext/mysqli/tests/004.phpt89
-rw-r--r--ext/mysqli/tests/005.phpt61
-rw-r--r--ext/mysqli/tests/006.phpt76
-rw-r--r--ext/mysqli/tests/007.phpt76
-rw-r--r--ext/mysqli/tests/008.phpt76
-rw-r--r--ext/mysqli/tests/009.phpt116
-rw-r--r--ext/mysqli/tests/010.phpt79
-rw-r--r--ext/mysqli/tests/011.phpt78
-rw-r--r--ext/mysqli/tests/012.phpt77
-rw-r--r--ext/mysqli/tests/013.phpt72
-rw-r--r--ext/mysqli/tests/014.phpt97
-rw-r--r--ext/mysqli/tests/015.phpt94
-rw-r--r--ext/mysqli/tests/016.phpt33
-rw-r--r--ext/mysqli/tests/017.phpt43
-rw-r--r--ext/mysqli/tests/018.phpt33
-rw-r--r--ext/mysqli/tests/019.phpt94
-rw-r--r--ext/mysqli/tests/020.phpt98
-rw-r--r--ext/mysqli/tests/021.phpt59
-rw-r--r--ext/mysqli/tests/022.phpt64
-rw-r--r--ext/mysqli/tests/023.phpt83
-rw-r--r--ext/mysqli/tests/024.phpt83
-rw-r--r--ext/mysqli/tests/025.phpt88
-rw-r--r--ext/mysqli/tests/026.phpt65
-rw-r--r--ext/mysqli/tests/027.phpt24
-rw-r--r--ext/mysqli/tests/028.phpt24
-rw-r--r--ext/mysqli/tests/029.phpt42
-rw-r--r--ext/mysqli/tests/030.phpt30
-rw-r--r--ext/mysqli/tests/031.phpt30
-rw-r--r--ext/mysqli/tests/032.phpt42
-rw-r--r--ext/mysqli/tests/033.phpt25
-rw-r--r--ext/mysqli/tests/034.phpt25
-rw-r--r--ext/mysqli/tests/035.phpt24
-rw-r--r--ext/mysqli/tests/036.phpt63
-rw-r--r--ext/mysqli/tests/037.phpt53
-rw-r--r--ext/mysqli/tests/038.phpt47
-rw-r--r--ext/mysqli/tests/039.phpt30
-rw-r--r--ext/mysqli/tests/040.phpt47
-rw-r--r--ext/mysqli/tests/041.phpt38
-rw-r--r--ext/mysqli/tests/042.phpt79
-rw-r--r--ext/mysqli/tests/043.phpt59
-rw-r--r--ext/mysqli/tests/044.phpt26
-rw-r--r--ext/mysqli/tests/045.phpt53
-rw-r--r--ext/mysqli/tests/046.phpt50
-rw-r--r--ext/mysqli/tests/047.phpt237
-rw-r--r--ext/mysqli/tests/048.phpt79
-rw-r--r--ext/mysqli/tests/049.phpt33
-rw-r--r--ext/mysqli/tests/050.phpt24
-rw-r--r--ext/mysqli/tests/051.phpt25
-rw-r--r--ext/mysqli/tests/052.phpt25
-rw-r--r--ext/mysqli/tests/053.phpt23
-rw-r--r--ext/mysqli/tests/054.phpt23
-rw-r--r--ext/mysqli/tests/055.phpt22
-rw-r--r--ext/mysqli/tests/056.phpt24
-rw-r--r--ext/mysqli/tests/057.phpt113
-rw-r--r--ext/mysqli/tests/058.phpt73
-rw-r--r--ext/mysqli/tests/059.phpt57
-rw-r--r--ext/mysqli/tests/060.phpt74
-rw-r--r--ext/mysqli/tests/061.phpt78
-rw-r--r--ext/mysqli/tests/062.phpt30
-rw-r--r--ext/mysqli/tests/063.phpt24
-rw-r--r--ext/mysqli/tests/064.phpt24
-rw-r--r--ext/mysqli/tests/065.phpt55
-rw-r--r--ext/mysqli/tests/066.phpt43
-rw-r--r--ext/mysqli/tests/067.phpt81
-rw-r--r--ext/mysqli/tests/068.phpt11
-rw-r--r--ext/mysqli/tests/069.phpt38
-rw-r--r--ext/mysqli/tests/070.phpt19
-rw-r--r--ext/mysqli/tests/071.phpt74
-rw-r--r--ext/mysqli/tests/072.phpt32
-rw-r--r--ext/mysqli/tests/073.phpt24
-rw-r--r--ext/mysqli/tests/074.phpt34
-rw-r--r--ext/mysqli/tests/bug28817.phpt42
-rw-r--r--ext/mysqli/tests/bug29311.phpt51
-rw-r--r--ext/mysqli/tests/bug30967.phpt26
-rw-r--r--ext/mysqli/tests/bug31141.phpt28
-rw-r--r--ext/mysqli/tests/bug31668.phpt61
-rw-r--r--ext/mysqli/tests/bug32405.phpt53
-rw-r--r--ext/mysqli/tests/bug33090.phpt24
-rw-r--r--ext/mysqli/tests/bug33263.phpt37
-rw-r--r--ext/mysqli/tests/bug33491.phpt29
-rw-r--r--ext/mysqli/tests/bug34785.phpt50
-rw-r--r--ext/mysqli/tests/bug34810.phpt146
-rw-r--r--ext/mysqli/tests/bug35103.phpt82
-rw-r--r--ext/mysqli/tests/bug35517.phpt56
-rw-r--r--ext/mysqli/tests/bug35759.phpt58
-rw-r--r--ext/mysqli/tests/bug36420.phpt28
-rw-r--r--ext/mysqli/tests/bug36745.phpt37
-rw-r--r--ext/mysqli/tests/bug36802.phpt41
-rw-r--r--ext/mysqli/tests/bug36949.phpt63
-rw-r--r--ext/mysqli/tests/bug37090.phpt48
-rw-r--r--ext/mysqli/tests/bug38003.phpt20
-rw-r--r--ext/mysqli/tests/bug38710.phpt24
-rw-r--r--ext/mysqli/tests/bug39457.phpt21
-rw-r--r--ext/mysqli/tests/bug42378.phpt197
-rw-r--r--ext/mysqli/tests/bug42548.phpt75
-rw-r--r--ext/mysqli/tests/bug44897.phpt89
-rw-r--r--ext/mysqli/tests/bug45019.phpt59
-rw-r--r--ext/mysqli/tests/bug45289.phpt40
-rw-r--r--ext/mysqli/tests/bug46109.phpt18
-rw-r--r--ext/mysqli/tests/bug46614.phpt30
-rw-r--r--ext/mysqli/tests/bug47050.phpt34
-rw-r--r--ext/mysqli/tests/bug48909.phpt46
-rw-r--r--ext/mysqli/tests/bug49027.phpt62
-rw-r--r--ext/mysqli/tests/bug49442.phpt130
-rw-r--r--ext/mysqli/tests/bug50772.phpt36
-rw-r--r--ext/mysqli/tests/bug51605.phpt44
-rw-r--r--ext/mysqli/tests/bug51647.phpt81
-rw-r--r--ext/mysqli/tests/bug52082.phpt50
-rw-r--r--ext/mysqli/tests/bug52891.phpt160
-rw-r--r--ext/mysqli/tests/bug53503.phpt66
-rw-r--r--ext/mysqli/tests/bug54221.phpt47
-rw-r--r--ext/mysqli/tests/bug54674.phpt31
-rw-r--r--ext/mysqli/tests/bug55283.phpt75
-rw-r--r--ext/mysqli/tests/bug55582.phpt41
-rw-r--r--ext/mysqli/tests/bug55653.phpt36
-rw-r--r--ext/mysqli/tests/bug55859.phpt20
-rw-r--r--ext/mysqli/tests/bug62046.phpt40
-rw-r--r--ext/mysqli/tests/bug62885.phpt26
-rw-r--r--ext/mysqli/tests/bug63398.phpt36
-rw-r--r--ext/mysqli/tests/bug_mysql_49406.phpt107
-rw-r--r--ext/mysqli/tests/cacert.pem17
-rw-r--r--ext/mysqli/tests/clean_table.inc14
-rw-r--r--ext/mysqli/tests/client-cert.pem46
-rw-r--r--ext/mysqli/tests/client-key.pem15
-rw-r--r--ext/mysqli/tests/connect.inc273
-rw-r--r--ext/mysqli/tests/local_infile_tools.inc156
-rw-r--r--ext/mysqli/tests/mysqli_affected_rows.phpt135
-rw-r--r--ext/mysqli/tests/mysqli_affected_rows_oo.phpt114
-rw-r--r--ext/mysqli/tests/mysqli_auth_pam.phpt98
-rw-r--r--ext/mysqli/tests/mysqli_autocommit.phpt147
-rw-r--r--ext/mysqli/tests/mysqli_autocommit_oo.phpt137
-rw-r--r--ext/mysqli/tests/mysqli_change_user.phpt112
-rw-r--r--ext/mysqli/tests/mysqli_change_user_get_lock.phpt106
-rw-r--r--ext/mysqli/tests/mysqli_change_user_insert_id.phpt65
-rw-r--r--ext/mysqli/tests/mysqli_change_user_locks_temporary.phpt107
-rw-r--r--ext/mysqli/tests/mysqli_change_user_oo.phpt84
-rw-r--r--ext/mysqli/tests/mysqli_change_user_prepared_statements.phpt33
-rw-r--r--ext/mysqli/tests/mysqli_change_user_rollback.phpt70
-rw-r--r--ext/mysqli/tests/mysqli_change_user_set_names.phpt165
-rw-r--r--ext/mysqli/tests/mysqli_character_set.phpt111
-rw-r--r--ext/mysqli/tests/mysqli_character_set_name.phpt75
-rw-r--r--ext/mysqli/tests/mysqli_character_set_name_oo.phpt70
-rw-r--r--ext/mysqli/tests/mysqli_class_mysqli_driver_interface.phpt128
-rw-r--r--ext/mysqli/tests/mysqli_class_mysqli_driver_reflection.phpt92
-rw-r--r--ext/mysqli/tests/mysqli_class_mysqli_interface.phpt319
-rw-r--r--ext/mysqli/tests/mysqli_class_mysqli_properties_no_conn.phpt290
-rw-r--r--ext/mysqli/tests/mysqli_class_mysqli_reflection.phpt1246
-rw-r--r--ext/mysqli/tests/mysqli_class_mysqli_result_interface.phpt193
-rw-r--r--ext/mysqli/tests/mysqli_class_mysqli_result_reflection.phpt369
-rw-r--r--ext/mysqli/tests/mysqli_class_mysqli_stmt_interface.phpt198
-rw-r--r--ext/mysqli/tests/mysqli_class_mysqli_warning.phpt132
-rw-r--r--ext/mysqli/tests/mysqli_class_mysqli_warning_reflection.phpt116
-rw-r--r--ext/mysqli/tests/mysqli_close.phpt40
-rw-r--r--ext/mysqli/tests/mysqli_close_oo.phpt36
-rw-r--r--ext/mysqli/tests/mysqli_commit.phpt77
-rw-r--r--ext/mysqli/tests/mysqli_commit_oo.phpt79
-rw-r--r--ext/mysqli/tests/mysqli_connect.phpt175
-rw-r--r--ext/mysqli/tests/mysqli_connect_errno.phpt40
-rw-r--r--ext/mysqli/tests/mysqli_connect_error.phpt39
-rw-r--r--ext/mysqli/tests/mysqli_connect_oo.phpt153
-rw-r--r--ext/mysqli/tests/mysqli_connect_oo_defaults.phpt180
-rw-r--r--ext/mysqli/tests/mysqli_connect_oo_warnings.phpt57
-rw-r--r--ext/mysqli/tests/mysqli_connect_twice.phpt84
-rw-r--r--ext/mysqli/tests/mysqli_constants.phpt212
-rw-r--r--ext/mysqli/tests/mysqli_constants_categories.phpt24
-rw-r--r--ext/mysqli/tests/mysqli_data_seek.phpt74
-rw-r--r--ext/mysqli/tests/mysqli_data_seek_oo.phpt83
-rw-r--r--ext/mysqli/tests/mysqli_debug.phpt69
-rw-r--r--ext/mysqli/tests/mysqli_debug_append.phpt93
-rw-r--r--ext/mysqli/tests/mysqli_debug_control_string.phpt77
-rw-r--r--ext/mysqli/tests/mysqli_debug_ini.phpt53
-rw-r--r--ext/mysqli/tests/mysqli_debug_mysqlnd_control_string.phpt230
-rw-r--r--ext/mysqli/tests/mysqli_debug_mysqlnd_only.phpt128
-rw-r--r--ext/mysqli/tests/mysqli_disable_reads_from_master.phpt47
-rw-r--r--ext/mysqli/tests/mysqli_driver.phpt114
-rw-r--r--ext/mysqli/tests/mysqli_driver_unclonable.phpt13
-rw-r--r--ext/mysqli/tests/mysqli_dump_debug_info.phpt44
-rw-r--r--ext/mysqli/tests/mysqli_dump_debug_info_oo.phpt38
-rw-r--r--ext/mysqli/tests/mysqli_embedded_connect.phpt32
-rw-r--r--ext/mysqli/tests/mysqli_enable_reads_from_master.phpt43
-rw-r--r--ext/mysqli/tests/mysqli_errno.phpt52
-rw-r--r--ext/mysqli/tests/mysqli_errno_oo.phpt49
-rw-r--r--ext/mysqli/tests/mysqli_error.phpt49
-rw-r--r--ext/mysqli/tests/mysqli_error_oo.phpt46
-rw-r--r--ext/mysqli/tests/mysqli_error_unicode.phpt51
-rw-r--r--ext/mysqli/tests/mysqli_expire_password.phpt145
-rw-r--r--ext/mysqli/tests/mysqli_explain_metadata.phpt162
-rw-r--r--ext/mysqli/tests/mysqli_fetch_all.phpt440
-rw-r--r--ext/mysqli/tests/mysqli_fetch_all_oo.phpt440
-rw-r--r--ext/mysqli/tests/mysqli_fetch_array.phpt374
-rw-r--r--ext/mysqli/tests/mysqli_fetch_array_assoc.phpt49
-rw-r--r--ext/mysqli/tests/mysqli_fetch_array_large.phpt169
-rw-r--r--ext/mysqli/tests/mysqli_fetch_array_many_rows.phpt115
-rw-r--r--ext/mysqli/tests/mysqli_fetch_array_oo.phpt362
-rw-r--r--ext/mysqli/tests/mysqli_fetch_assoc.phpt119
-rw-r--r--ext/mysqli/tests/mysqli_fetch_assoc_bit.phpt117
-rw-r--r--ext/mysqli/tests/mysqli_fetch_assoc_no_alias.phpt142
-rw-r--r--ext/mysqli/tests/mysqli_fetch_assoc_no_alias_utf8.phpt164
-rw-r--r--ext/mysqli/tests/mysqli_fetch_assoc_oo.phpt86
-rw-r--r--ext/mysqli/tests/mysqli_fetch_assoc_zerofill.phpt78
-rw-r--r--ext/mysqli/tests/mysqli_fetch_field.phpt177
-rw-r--r--ext/mysqli/tests/mysqli_fetch_field_direct.phpt83
-rw-r--r--ext/mysqli/tests/mysqli_fetch_field_direct_oo.phpt92
-rw-r--r--ext/mysqli/tests/mysqli_fetch_field_flags.phpt243
-rw-r--r--ext/mysqli/tests/mysqli_fetch_field_oo.phpt129
-rw-r--r--ext/mysqli/tests/mysqli_fetch_field_types.phpt126
-rw-r--r--ext/mysqli/tests/mysqli_fetch_fields.phpt121
-rw-r--r--ext/mysqli/tests/mysqli_fetch_lengths.phpt55
-rw-r--r--ext/mysqli/tests/mysqli_fetch_lengths_oo.phpt50
-rw-r--r--ext/mysqli/tests/mysqli_fetch_object.phpt156
-rw-r--r--ext/mysqli/tests/mysqli_fetch_object_no_constructor.phpt65
-rw-r--r--ext/mysqli/tests/mysqli_fetch_object_no_object.phpt27
-rw-r--r--ext/mysqli/tests/mysqli_fetch_object_oo.phpt134
-rw-r--r--ext/mysqli/tests/mysqli_fetch_row.phpt59
-rw-r--r--ext/mysqli/tests/mysqli_field_count.phpt63
-rw-r--r--ext/mysqli/tests/mysqli_field_seek.phpt251
-rw-r--r--ext/mysqli/tests/mysqli_field_tell.phpt110
-rw-r--r--ext/mysqli/tests/mysqli_fork.phpt252
-rw-r--r--ext/mysqli/tests/mysqli_free_result.phpt78
-rw-r--r--ext/mysqli/tests/mysqli_get_charset.phpt115
-rw-r--r--ext/mysqli/tests/mysqli_get_client_info.phpt18
-rw-r--r--ext/mysqli/tests/mysqli_get_client_stats.phpt1294
-rw-r--r--ext/mysqli/tests/mysqli_get_client_stats_implicit_free.phpt46
-rw-r--r--ext/mysqli/tests/mysqli_get_client_stats_off.phpt48
-rw-r--r--ext/mysqli/tests/mysqli_get_client_stats_ps.phpt106
-rw-r--r--ext/mysqli/tests/mysqli_get_client_stats_skipped.phpt52
-rw-r--r--ext/mysqli/tests/mysqli_get_client_version.phpt14
-rw-r--r--ext/mysqli/tests/mysqli_get_connection_stats.phpt87
-rw-r--r--ext/mysqli/tests/mysqli_get_connection_stats_off.phpt53
-rw-r--r--ext/mysqli/tests/mysqli_get_host_info.phpt35
-rw-r--r--ext/mysqli/tests/mysqli_get_proto_info.phpt29
-rw-r--r--ext/mysqli/tests/mysqli_get_server_info.phpt33
-rw-r--r--ext/mysqli/tests/mysqli_get_server_version.phpt28
-rw-r--r--ext/mysqli/tests/mysqli_get_warnings.phpt160
-rw-r--r--ext/mysqli/tests/mysqli_info.phpt101
-rw-r--r--ext/mysqli/tests/mysqli_init.phpt25
-rw-r--r--ext/mysqli/tests/mysqli_insert_id.phpt140
-rw-r--r--ext/mysqli/tests/mysqli_insert_id_variation.phpt103
-rw-r--r--ext/mysqli/tests/mysqli_insert_packet_overflow.phpt116
-rw-r--r--ext/mysqli/tests/mysqli_kill.phpt145
-rw-r--r--ext/mysqli/tests/mysqli_last_insert_id.phpt194
-rw-r--r--ext/mysqli/tests/mysqli_max_links.phpt76
-rw-r--r--ext/mysqli/tests/mysqli_more_results.phpt114
-rw-r--r--ext/mysqli/tests/mysqli_multi_query.phpt162
-rw-r--r--ext/mysqli/tests/mysqli_mysqli_result_invalid_mode.phpt30
-rw-r--r--ext/mysqli/tests/mysqli_mysqlnd_read_timeout.phpt36
-rw-r--r--ext/mysqli/tests/mysqli_mysqlnd_read_timeout_long.phpt48
-rw-r--r--ext/mysqli/tests/mysqli_mysqlnd_read_timeout_zero.phpt47
-rw-r--r--ext/mysqli/tests/mysqli_next_result.phpt124
-rw-r--r--ext/mysqli/tests/mysqli_no_reconnect.phpt127
-rw-r--r--ext/mysqli/tests/mysqli_num_fields.phpt57
-rw-r--r--ext/mysqli/tests/mysqli_num_rows.phpt89
-rw-r--r--ext/mysqli/tests/mysqli_options.phpt143
-rw-r--r--ext/mysqli/tests/mysqli_options_init_command.phpt78
-rw-r--r--ext/mysqli/tests/mysqli_options_int_and_float_native.phpt109
-rw-r--r--ext/mysqli/tests/mysqli_options_openbasedir.phpt23
-rw-r--r--ext/mysqli/tests/mysqli_pconn_conn_multiple.phpt161
-rw-r--r--ext/mysqli/tests/mysqli_pconn_disabled.phpt62
-rw-r--r--ext/mysqli/tests/mysqli_pconn_kill.phpt95
-rw-r--r--ext/mysqli/tests/mysqli_pconn_limits.phpt98
-rw-r--r--ext/mysqli/tests/mysqli_pconn_max_links.phpt196
-rw-r--r--ext/mysqli/tests/mysqli_pconn_reuse.phpt91
-rw-r--r--ext/mysqli/tests/mysqli_pconn_twice.phpt77
-rw-r--r--ext/mysqli/tests/mysqli_pconnect.phpt72
-rw-r--r--ext/mysqli/tests/mysqli_phpinfo.phpt72
-rw-r--r--ext/mysqli/tests/mysqli_ping.phpt47
-rw-r--r--ext/mysqli/tests/mysqli_poll.phpt137
-rw-r--r--ext/mysqli/tests/mysqli_poll_kill.phpt199
-rw-r--r--ext/mysqli/tests/mysqli_poll_mixing_insert_select.phpt184
-rw-r--r--ext/mysqli/tests/mysqli_poll_reference.phpt220
-rw-r--r--ext/mysqli/tests/mysqli_prepare.phpt135
-rw-r--r--ext/mysqli/tests/mysqli_prepare_no_object.phpt46
-rw-r--r--ext/mysqli/tests/mysqli_ps_select_union.phpt275
-rw-r--r--ext/mysqli/tests/mysqli_query.phpt141
-rw-r--r--ext/mysqli/tests/mysqli_query_iterators.phpt201
-rw-r--r--ext/mysqli/tests/mysqli_query_local_infile_large.phpt103
-rw-r--r--ext/mysqli/tests/mysqli_query_stored_proc.phpt195
-rw-r--r--ext/mysqli/tests/mysqli_query_unicode.phpt133
-rw-r--r--ext/mysqli/tests/mysqli_real_connect.phpt221
-rw-r--r--ext/mysqli/tests/mysqli_real_connect_pconn.phpt155
-rw-r--r--ext/mysqli/tests/mysqli_real_escape_string.phpt58
-rw-r--r--ext/mysqli/tests/mysqli_real_escape_string_big5.phpt82
-rw-r--r--ext/mysqli/tests/mysqli_real_escape_string_eucjpms.phpt75
-rw-r--r--ext/mysqli/tests/mysqli_real_escape_string_euckr.phpt74
-rw-r--r--ext/mysqli/tests/mysqli_real_escape_string_gb2312.phpt75
-rw-r--r--ext/mysqli/tests/mysqli_real_escape_string_gbk.phpt77
-rw-r--r--ext/mysqli/tests/mysqli_real_escape_string_nobackslash.phpt65
-rw-r--r--ext/mysqli/tests/mysqli_real_escape_string_sjis.phpt56
-rw-r--r--ext/mysqli/tests/mysqli_real_escape_string_unicode.phpt88
-rw-r--r--ext/mysqli/tests/mysqli_real_query.phpt113
-rw-r--r--ext/mysqli/tests/mysqli_reconnect.phpt130
-rw-r--r--ext/mysqli/tests/mysqli_report.phpt307
-rw-r--r--ext/mysqli/tests/mysqli_report_wo_ps.phpt113
-rw-r--r--ext/mysqli/tests/mysqli_result_references.phpt154
-rw-r--r--ext/mysqli/tests/mysqli_result_references_mysqlnd.phpt119
-rw-r--r--ext/mysqli/tests/mysqli_result_unclonable.phpt24
-rw-r--r--ext/mysqli/tests/mysqli_rollback.phpt77
-rw-r--r--ext/mysqli/tests/mysqli_select_db.phpt112
-rw-r--r--ext/mysqli/tests/mysqli_send_query.phpt50
-rw-r--r--ext/mysqli/tests/mysqli_set_charset.phpt134
-rw-r--r--ext/mysqli/tests/mysqli_set_local_infile_default.phpt132
-rw-r--r--ext/mysqli/tests/mysqli_set_local_infile_handler.phpt196
-rw-r--r--ext/mysqli/tests/mysqli_set_local_infile_handler_bad_character.phpt82
-rw-r--r--ext/mysqli/tests/mysqli_set_local_infile_handler_buffer_overflow.phpt60
-rw-r--r--ext/mysqli/tests/mysqli_set_local_infile_handler_close_link.phpt61
-rw-r--r--ext/mysqli/tests/mysqli_set_local_infile_handler_closefile.phpt70
-rw-r--r--ext/mysqli/tests/mysqli_set_local_infile_handler_closures.phpt62
-rw-r--r--ext/mysqli/tests/mysqli_set_local_infile_handler_kill_link.phpt61
-rw-r--r--ext/mysqli/tests/mysqli_set_local_infile_handler_negative_len.phpt58
-rw-r--r--ext/mysqli/tests/mysqli_set_local_infile_handler_nested_call.phpt107
-rw-r--r--ext/mysqli/tests/mysqli_set_local_infile_handler_new_query.phpt71
-rw-r--r--ext/mysqli/tests/mysqli_set_local_infile_handler_nofileop.phpt70
-rw-r--r--ext/mysqli/tests/mysqli_set_local_infile_handler_openbasedir.phpt115
-rw-r--r--ext/mysqli/tests/mysqli_set_local_infile_handler_replace_buffer.phpt78
-rw-r--r--ext/mysqli/tests/mysqli_set_local_infile_handler_short_len.phpt101
-rw-r--r--ext/mysqli/tests/mysqli_set_local_infile_handler_unregister.phpt64
-rw-r--r--ext/mysqli/tests/mysqli_set_opt.phpt69
-rw-r--r--ext/mysqli/tests/mysqli_sqlstate.phpt50
-rw-r--r--ext/mysqli/tests/mysqli_ssl_set.phpt61
-rw-r--r--ext/mysqli/tests/mysqli_stat.phpt40
-rw-r--r--ext/mysqli/tests/mysqli_stmt_affected_rows.phpt252
-rw-r--r--ext/mysqli/tests/mysqli_stmt_attr_get.phpt70
-rw-r--r--ext/mysqli/tests/mysqli_stmt_attr_get_prefetch.phpt29
-rw-r--r--ext/mysqli/tests/mysqli_stmt_attr_set.phpt277
-rw-r--r--ext/mysqli/tests/mysqli_stmt_bind_limits.phpt129
-rw-r--r--ext/mysqli/tests/mysqli_stmt_bind_param.phpt404
-rw-r--r--ext/mysqli/tests/mysqli_stmt_bind_param_call_user_func.phpt366
-rw-r--r--ext/mysqli/tests/mysqli_stmt_bind_param_check_param_no_change.phpt110
-rw-r--r--ext/mysqli/tests/mysqli_stmt_bind_param_many_columns.phpt103
-rw-r--r--ext/mysqli/tests/mysqli_stmt_bind_param_references.phpt207
-rw-r--r--ext/mysqli/tests/mysqli_stmt_bind_param_type_juggling.phpt127
-rw-r--r--ext/mysqli/tests/mysqli_stmt_bind_result.phpt331
-rw-r--r--ext/mysqli/tests/mysqli_stmt_bind_result_bit.phpt159
-rw-r--r--ext/mysqli/tests/mysqli_stmt_bind_result_format.phpt337
-rw-r--r--ext/mysqli/tests/mysqli_stmt_bind_result_references.phpt314
-rw-r--r--ext/mysqli/tests/mysqli_stmt_bind_result_zerofill.phpt97
-rw-r--r--ext/mysqli/tests/mysqli_stmt_close.phpt91
-rw-r--r--ext/mysqli/tests/mysqli_stmt_data_seek.phpt99
-rw-r--r--ext/mysqli/tests/mysqli_stmt_datatype_change.phpt94
-rw-r--r--ext/mysqli/tests/mysqli_stmt_errno.phpt68
-rw-r--r--ext/mysqli/tests/mysqli_stmt_error.phpt68
-rw-r--r--ext/mysqli/tests/mysqli_stmt_execute.phpt150
-rw-r--r--ext/mysqli/tests/mysqli_stmt_execute_stored_proc.phpt198
-rw-r--r--ext/mysqli/tests/mysqli_stmt_execute_stored_proc_next_result.phpt131
-rw-r--r--ext/mysqli/tests/mysqli_stmt_execute_stored_proc_out.phpt81
-rw-r--r--ext/mysqli/tests/mysqli_stmt_fetch.phpt98
-rw-r--r--ext/mysqli/tests/mysqli_stmt_fetch_bit.phpt76
-rw-r--r--ext/mysqli/tests/mysqli_stmt_fetch_fields_win32_unicode.phpt56
-rw-r--r--ext/mysqli/tests/mysqli_stmt_fetch_geom.phpt141
-rw-r--r--ext/mysqli/tests/mysqli_stmt_field_count.phpt100
-rw-r--r--ext/mysqli/tests/mysqli_stmt_free_result.phpt86
-rw-r--r--ext/mysqli/tests/mysqli_stmt_get_result.phpt187
-rw-r--r--ext/mysqli/tests/mysqli_stmt_get_result2.phpt176
-rw-r--r--ext/mysqli/tests/mysqli_stmt_get_result_bit.phpt133
-rw-r--r--ext/mysqli/tests/mysqli_stmt_get_result_field_count.phpt50
-rw-r--r--ext/mysqli/tests/mysqli_stmt_get_result_geom.phpt143
-rw-r--r--ext/mysqli/tests/mysqli_stmt_get_result_metadata.phpt237
-rw-r--r--ext/mysqli/tests/mysqli_stmt_get_result_metadata_fetch_field.phpt176
-rw-r--r--ext/mysqli/tests/mysqli_stmt_get_result_non_select.phpt95
-rw-r--r--ext/mysqli/tests/mysqli_stmt_get_result_seek.phpt129
-rw-r--r--ext/mysqli/tests/mysqli_stmt_get_result_types.phpt259
-rw-r--r--ext/mysqli/tests/mysqli_stmt_get_warnings.phpt107
-rw-r--r--ext/mysqli/tests/mysqli_stmt_init.phpt58
-rw-r--r--ext/mysqli/tests/mysqli_stmt_insert_id.phpt77
-rw-r--r--ext/mysqli/tests/mysqli_stmt_num_rows.phpt118
-rw-r--r--ext/mysqli/tests/mysqli_stmt_param_count.phpt72
-rw-r--r--ext/mysqli/tests/mysqli_stmt_prepare.phpt56
-rw-r--r--ext/mysqli/tests/mysqli_stmt_reset.phpt112
-rw-r--r--ext/mysqli/tests/mysqli_stmt_result_metadata.phpt134
-rw-r--r--ext/mysqli/tests/mysqli_stmt_result_metadata_sqltests.phpt232
-rw-r--r--ext/mysqli/tests/mysqli_stmt_send_long_data.phpt135
-rw-r--r--ext/mysqli/tests/mysqli_stmt_send_long_data_packet_size_libmysql.phpt98
-rw-r--r--ext/mysqli/tests/mysqli_stmt_send_long_data_packet_size_mysqlnd.phpt103
-rw-r--r--ext/mysqli/tests/mysqli_stmt_sqlstate.phpt63
-rw-r--r--ext/mysqli/tests/mysqli_stmt_store_result.phpt90
-rw-r--r--ext/mysqli/tests/mysqli_stmt_unclonable.phpt25
-rw-r--r--ext/mysqli/tests/mysqli_store_result.phpt64
-rw-r--r--ext/mysqli/tests/mysqli_thread_id.phpt44
-rw-r--r--ext/mysqli/tests/mysqli_thread_safe.phpt16
-rw-r--r--ext/mysqli/tests/mysqli_unclonable.phpt23
-rw-r--r--ext/mysqli/tests/mysqli_use_result.phpt66
-rw-r--r--ext/mysqli/tests/mysqli_warning_count.phpt52
-rw-r--r--ext/mysqli/tests/mysqli_warning_unclonable.phpt41
-rw-r--r--ext/mysqli/tests/reflection_tools.inc121
-rw-r--r--ext/mysqli/tests/skipif.inc5
-rw-r--r--ext/mysqli/tests/skipifconnectfailure.inc10
-rw-r--r--ext/mysqli/tests/skipifemb.inc5
-rw-r--r--ext/mysqli/tests/skipifnotemb.inc5
-rw-r--r--ext/mysqli/tests/skipifunicode.inc5
-rw-r--r--ext/mysqli/tests/table.inc23
393 files changed, 39449 insertions, 0 deletions
diff --git a/ext/mysqli/tests/001.phpt b/ext/mysqli/tests/001.phpt
new file mode 100644
index 0000000..ed09b2e
--- /dev/null
+++ b/ext/mysqli/tests/001.phpt
@@ -0,0 +1,63 @@
+--TEST--
+mysqli connect
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $test = "";
+
+ /*** test mysqli_connect localhost:port ***/
+ $link = my_mysqli_connect($host, $user, $passwd, "", $port, $socket);
+ $test .= ($link) ? "1" : "0";
+ mysqli_close($link);
+
+ /*** test mysqli_real_connect ***/
+ $link = mysqli_init();
+ $test.= (my_mysqli_real_connect($link, $host, $user, $passwd, "", $port, $socket) )
+ ? "1" : "0";
+ mysqli_close($link);
+
+ /*** test mysqli_real_connect with db ***/
+ $link = mysqli_init();
+ $test .= (my_mysqli_real_connect($link, $host, $user, $passwd, $db, $port, $socket))
+ ? "1" : "0";
+ mysqli_close($link);
+
+ /*** test mysqli_real_connect with port ***/
+ $link = mysqli_init();
+ $test .= (my_mysqli_real_connect($link, $host, $user, $passwd, $db, $port, $socket))
+ ? "1":"0";
+ mysqli_close($link);
+
+ /* temporary addition for Kent's setup, Win32 box */
+ for ($i = 0; $i < 10; $i++) {
+ if (!$link = mysqli_init())
+ printf("[001 + %d] mysqli_init() failed, [%d] %s\n", $i, mysqli_connect_errno(), mysqli_connect_error());
+
+ if (!my_mysqli_real_connect($link, $host, $user, $passwd, $db, $port, $socket))
+ printf("[002 + %d] mysqli_real_connect() failed, [%d] %s\n", $i, mysqli_connect_errno(), mysqli_connect_error());
+
+ mysqli_close($link);
+ }
+
+ /*** test mysqli_real_connect compressed ***/
+ /*
+ $link = mysqli_init();
+ $test .= (my_mysqli_real_connect($link, $host, $user, $passwd, $db, $port, $socket, MYSQLI_CLIENT_COMPRESS))
+ ? "1" : "0";
+ mysqli_close($link);
+ */
+ /* todo ssl connections */
+
+ var_dump($test);
+ print "done!";
+?>
+--EXPECTF--
+%s(4) "1111"
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/002.phpt b/ext/mysqli/tests/002.phpt
new file mode 100644
index 0000000..522c99e
--- /dev/null
+++ b/ext/mysqli/tests/002.phpt
@@ -0,0 +1,85 @@
+--TEST--
+mysqli bind_result 1
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ /*** test mysqli_connect 127.0.0.1 ***/
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+ if (!mysqli_query($link, "DROP TABLE IF EXISTS test_fetch_null"))
+ printf("[002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $rc = mysqli_query($link,"CREATE TABLE test_fetch_null(col1 tinyint, col2 smallint,
+ col3 int, col4 bigint,
+ col5 float, col6 double,
+ col7 date, col8 time,
+ col9 varbinary(10),
+ col10 varchar(50),
+ col11 char(20)) ENGINE=" . $engine);
+
+ if (!$rc)
+ printf("[003] Cannot create table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $rc = mysqli_query($link, "INSERT INTO test_fetch_null(col1,col10, col11) VALUES(1,'foo1', 1000),(2,'foo2', 88),(3,'foo3', 389789)");
+ if (!$rc)
+ printf("[004] Cannot insert records, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $stmt = mysqli_prepare($link, "SELECT col1, col2, col3, col4, col5, col6, col7, col8, col9, col10, col11 from test_fetch_null ORDER BY col1");
+ mysqli_stmt_bind_result($stmt, $c1, $c2, $c3, $c4, $c5, $c6, $c7, $c8, $c9, $c10, $c11);
+ mysqli_stmt_execute($stmt);
+
+ mysqli_stmt_fetch($stmt);
+
+ $test = array($c1,$c2,$c3,$c4,$c5,$c6,$c7,$c8,$c9,$c10,$c11);
+
+ var_dump($test);
+
+ mysqli_stmt_close($stmt);
+ @mysqli_query($link, "DROP TABLE IF EXISTS test_fetch_null");
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS test_fetch_null"))
+ printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+mysqli_close($link);
+?>
+--EXPECTF--
+array(11) {
+ [0]=>
+ int(1)
+ [1]=>
+ NULL
+ [2]=>
+ NULL
+ [3]=>
+ NULL
+ [4]=>
+ NULL
+ [5]=>
+ NULL
+ [6]=>
+ NULL
+ [7]=>
+ NULL
+ [8]=>
+ NULL
+ [9]=>
+ %unicode|string%(4) "foo1"
+ [10]=>
+ %unicode|string%(4) "1000"
+}
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/003.phpt b/ext/mysqli/tests/003.phpt
new file mode 100644
index 0000000..9374763
--- /dev/null
+++ b/ext/mysqli/tests/003.phpt
@@ -0,0 +1,103 @@
+--TEST--
+mysqli connect
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+ mysqli_query($link, "SET sql_mode=''");
+
+ if (!mysqli_query($link,"DROP TABLE IF EXISTS test_bind_result"))
+ printf("[001] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $rc = @mysqli_query($link,"CREATE TABLE test_bind_result(
+ c1 date,
+ c2 time,
+ c3 timestamp(14),
+ c4 year,
+ c5 datetime,
+ c6 timestamp(4),
+ c7 timestamp(6)) ENGINE=" . $engine);
+
+ /*
+ Seems that not all MySQL 6.0 installations use defaults that ignore the display widths.
+ From the manual:
+ From MySQL 4.1.0 on, TIMESTAMP display format differs from that of earlier MySQL releases:
+ [...]
+ Display widths (used as described in the preceding section) are no longer supported.
+ In other words, for declarations such as TIMESTAMP(2), TIMESTAMP(4), and so on,
+ the display width is ignored.
+ [...]
+ */
+ if (!$rc)
+ $rc = @mysqli_query($link,"CREATE TABLE test_bind_result(
+ c1 date,
+ c2 time,
+ c3 timestamp,
+ c4 year,
+ c5 datetime,
+ c6 timestamp,
+ c7 timestamp) ENGINE=" . $engine);
+
+ if (!$rc)
+ printf("[002] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $rc = mysqli_query($link, "INSERT INTO test_bind_result VALUES(
+ '2002-01-02',
+ '12:49:00',
+ '2002-01-02 17:46:59',
+ 2010,
+ '2010-07-10',
+ '2020','1999-12-29')");
+ if (!$rc)
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $stmt = mysqli_prepare($link, "SELECT c1, c2, c3, c4, c5, c6, c7 FROM test_bind_result");
+ mysqli_stmt_bind_result($stmt, $c1, $c2, $c3, $c4, $c5, $c6, $c7);
+ mysqli_stmt_execute($stmt);
+ mysqli_stmt_fetch($stmt);
+
+ $test = array($c1,$c2,$c3,$c4,$c5,$c6,$c7);
+
+ var_dump($test);
+
+ mysqli_stmt_close($stmt);
+ mysqli_query($link, "DROP TABLE IF EXISTS test_bind_result");
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS test_bind_result"))
+ printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+mysqli_close($link);
+?>
+--EXPECTF--
+array(7) {
+ [0]=>
+ %unicode|string%(10) "2002-01-02"
+ [1]=>
+ %unicode|string%(8) "12:49:00"
+ [2]=>
+ %unicode|string%(19) "2002-01-02 17:46:59"
+ [3]=>
+ int(2010)
+ [4]=>
+ %unicode|string%(19) "2010-07-10 00:00:00"
+ [5]=>
+ %unicode|string%(19) "0000-00-00 00:00:00"
+ [6]=>
+ %unicode|string%(19) "1999-12-29 00:00:00"
+}
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/004.phpt b/ext/mysqli/tests/004.phpt
new file mode 100644
index 0000000..010d6e1
--- /dev/null
+++ b/ext/mysqli/tests/004.phpt
@@ -0,0 +1,89 @@
+--TEST--
+mysqli fetch char/text
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ include ("connect.inc");
+
+ /*** test mysqli_connect 127.0.0.1 ***/
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+ mysqli_select_db($link, $db);
+
+ if (!mysqli_query($link,"DROP TABLE IF EXISTS test_bind_fetch"))
+ printf("[001] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link,"CREATE TABLE test_bind_fetch(c1 char(10), c2 text) ENGINE=" . $engine))
+ printf("[002] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, "INSERT INTO test_bind_fetch VALUES ('1234567890', 'this is a test0')"))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, "INSERT INTO test_bind_fetch VALUES ('1234567891', 'this is a test1')"))
+ printf("[004] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, "INSERT INTO test_bind_fetch VALUES ('1234567892', 'this is a test2')"))
+ printf("[005] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, "INSERT INTO test_bind_fetch VALUES ('1234567893', 'this is a test3')"))
+ printf("[006] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$stmt = mysqli_prepare($link, "SELECT * FROM test_bind_fetch ORDER BY c1"))
+ printf("[007] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $c1 = $c2 = NULL;
+ mysqli_stmt_bind_result($stmt, $c1, $c2);
+ mysqli_stmt_execute($stmt);
+ $i = 4;
+ while ($i--) {
+ mysqli_stmt_fetch($stmt);
+ $test = array($c1, $c2);
+ var_dump($test);
+ }
+
+ mysqli_stmt_close($stmt);
+ mysqli_query($link, "DROP TABLE IF EXISTS test_bind_fetch");
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS test_bind_fetch"))
+ printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+mysqli_close($link);
+?>
+--EXPECTF--
+array(2) {
+ [0]=>
+ %unicode|string%(10) "1234567890"
+ [1]=>
+ %unicode|string%(15) "this is a test0"
+}
+array(2) {
+ [0]=>
+ %unicode|string%(10) "1234567891"
+ [1]=>
+ %unicode|string%(15) "this is a test1"
+}
+array(2) {
+ [0]=>
+ %unicode|string%(10) "1234567892"
+ [1]=>
+ %unicode|string%(15) "this is a test2"
+}
+array(2) {
+ [0]=>
+ %unicode|string%(10) "1234567893"
+ [1]=>
+ %unicode|string%(15) "this is a test3"
+}
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/005.phpt b/ext/mysqli/tests/005.phpt
new file mode 100644
index 0000000..07292a1
--- /dev/null
+++ b/ext/mysqli/tests/005.phpt
@@ -0,0 +1,61 @@
+--TEST--
+mysqli fetch char/text long
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ /*** test mysqli_connect 127.0.0.1 ***/
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+ if (!mysqli_query($link, "DROP TABLE IF EXISTS test_bind_fetch"))
+ printf("[001] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, "CREATE TABLE test_bind_fetch(c1 char(10), c2 text) ENGINE=" . $engine))
+ printf("[002] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $a = str_repeat("A1", 32000);
+
+ mysqli_query($link, "INSERT INTO test_bind_fetch VALUES ('1234567890', '$a')");
+
+ $stmt = mysqli_prepare($link, "SELECT * FROM test_bind_fetch");
+ mysqli_stmt_bind_result($stmt, $c1, $c2);
+ mysqli_stmt_execute($stmt);
+ mysqli_stmt_fetch($stmt);
+
+ $test[] = $c1;
+ $test[] = ($a == $c2) ? "32K String ok" : "32K String failed";
+
+ var_dump($test);
+
+ /* this will crash with libmysql from PHP 5.0.6 (or earlier) to 5.3.0 */
+ mysqli_stmt_fetch($stmt);
+
+ mysqli_stmt_close($stmt);
+ mysqli_query($link, "DROP TABLE IF EXISTS test_bind_fetch");
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS test_bind_fetch"))
+ printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+mysqli_close($link);
+?>
+--EXPECTF--
+array(2) {
+ [0]=>
+ %unicode|string%(10) "1234567890"
+ [1]=>
+ %unicode|string%(13) "32K String ok"
+}
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/006.phpt b/ext/mysqli/tests/006.phpt
new file mode 100644
index 0000000..2043cc5
--- /dev/null
+++ b/ext/mysqli/tests/006.phpt
@@ -0,0 +1,76 @@
+--TEST--
+mysqli fetch long values
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ /*** test mysqli_connect 127.0.0.1 ***/
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+ if (!mysqli_query($link, "SET sql_mode=''"))
+ printf("[001] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link,"DROP TABLE IF EXISTS test_bind_fetch"))
+ printf("[002] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $rc = mysqli_query($link,"CREATE TABLE test_bind_fetch(c1 int unsigned,
+ c2 int unsigned,
+ c3 int,
+ c4 int,
+ c5 int,
+ c6 int unsigned,
+ c7 int) ENGINE=" . $engine);
+ if (!$rc)
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, "INSERT INTO test_bind_fetch VALUES (-23,35999,NULL,-500,-9999999,-0,0)"))
+ printf("[004] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $stmt = mysqli_prepare($link, "SELECT * FROM test_bind_fetch");
+ mysqli_stmt_bind_result($stmt, $c1, $c2, $c3, $c4, $c5, $c6, $c7);
+ mysqli_stmt_execute($stmt);
+ mysqli_stmt_fetch($stmt);
+
+ $test = array($c1,$c2,$c3,$c4,$c5,$c6,$c7);
+
+ var_dump($test);
+
+ mysqli_stmt_close($stmt);
+ mysqli_query($link, "DROP TABLE IF EXISTS test_bind_fetch");
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS test_bind_fetch"))
+ printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+mysqli_close($link);
+?>
+--EXPECT--
+array(7) {
+ [0]=>
+ int(0)
+ [1]=>
+ int(35999)
+ [2]=>
+ NULL
+ [3]=>
+ int(-500)
+ [4]=>
+ int(-9999999)
+ [5]=>
+ int(0)
+ [6]=>
+ int(0)
+}
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/007.phpt b/ext/mysqli/tests/007.phpt
new file mode 100644
index 0000000..26b5763
--- /dev/null
+++ b/ext/mysqli/tests/007.phpt
@@ -0,0 +1,76 @@
+--TEST--
+mysqli fetch short values
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ /*** test mysqli_connect 127.0.0.1 ***/
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+ if (!mysqli_query($link, "SET sql_mode=''"))
+ printf("[001] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, "DROP TABLE IF EXISTS test_bind_fetch"))
+ printf("[002] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $rc = mysqli_query($link, "CREATE TABLE test_bind_fetch(c1 smallint unsigned,
+ c2 smallint unsigned,
+ c3 smallint,
+ c4 smallint,
+ c5 smallint,
+ c6 smallint unsigned,
+ c7 smallint) ENGINE=" . $engine);
+ if (!$rc)
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, "INSERT INTO test_bind_fetch VALUES (-23,35999,NULL,-500,-9999999,+30,0)"))
+ printf("[004] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $stmt = mysqli_prepare($link, "SELECT * FROM test_bind_fetch");
+ mysqli_stmt_bind_result($stmt, $c1, $c2, $c3, $c4, $c5, $c6, $c7);
+ mysqli_stmt_execute($stmt);
+ mysqli_stmt_fetch($stmt);
+
+ $test = array($c1,$c2,$c3,$c4,$c5,$c6,$c7);
+
+ var_dump($test);
+
+ mysqli_stmt_close($stmt);
+ mysqli_query($link, "DROP TABLE IF EXISTS test_bind_fetch");
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS test_bind_fetch"))
+ printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+mysqli_close($link);
+?>
+--EXPECT--
+array(7) {
+ [0]=>
+ int(0)
+ [1]=>
+ int(35999)
+ [2]=>
+ NULL
+ [3]=>
+ int(-500)
+ [4]=>
+ int(-32768)
+ [5]=>
+ int(30)
+ [6]=>
+ int(0)
+}
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/008.phpt b/ext/mysqli/tests/008.phpt
new file mode 100644
index 0000000..0ae09df
--- /dev/null
+++ b/ext/mysqli/tests/008.phpt
@@ -0,0 +1,76 @@
+--TEST--
+mysqli fetch tinyint values
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ /*** test mysqli_connect 127.0.0.1 ***/
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+ if (!mysqli_query($link, "SET sql_mode=''"))
+ printf("[001] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, "DROP TABLE IF EXISTS test_bind_fetch"))
+ printf("[002] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $rc = mysqli_query($link, "CREATE TABLE test_bind_fetch(c1 tinyint,
+ c2 tinyint unsigned,
+ c3 tinyint not NULL,
+ c4 tinyint,
+ c5 tinyint,
+ c6 tinyint unsigned,
+ c7 tinyint) ENGINE=" . $engine);
+ if (!$rc)
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, "INSERT INTO test_bind_fetch VALUES (-23,300,0,-100,-127,+30,0)"))
+ printf("[004] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $stmt = mysqli_prepare($link, "SELECT * FROM test_bind_fetch");
+ mysqli_stmt_bind_result($stmt, $c1, $c2, $c3, $c4, $c5, $c6, $c7);
+ mysqli_stmt_execute($stmt);
+ mysqli_stmt_fetch($stmt);
+
+ $test = array($c1,$c2,$c3,$c4,$c5,$c6,$c7);
+
+ var_dump($test);
+
+ mysqli_stmt_close($stmt);
+ mysqli_query($link, "DROP TABLE IF EXISTS test_bind_fetch");
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS test_bind_fetch"))
+ printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+mysqli_close($link);
+?>
+--EXPECT--
+array(7) {
+ [0]=>
+ int(-23)
+ [1]=>
+ int(255)
+ [2]=>
+ int(0)
+ [3]=>
+ int(-100)
+ [4]=>
+ int(-127)
+ [5]=>
+ int(30)
+ [6]=>
+ int(0)
+}
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/009.phpt b/ext/mysqli/tests/009.phpt
new file mode 100644
index 0000000..30d42c3
--- /dev/null
+++ b/ext/mysqli/tests/009.phpt
@@ -0,0 +1,116 @@
+--TEST--
+mysqli fetch bigint values (ok to fail with 4.1.x)
+--SKIPIF--
+<?php
+ if (PHP_INT_SIZE == 8) {
+ echo 'skip test valid only for 32bit systems';
+ exit;
+ }
+ require_once('skipif.inc');
+ require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ /*** test mysqli_connect 127.0.0.1 ***/
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+ if (!mysqli_query($link, "SET sql_mode=''"))
+ printf("[001] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, "DROP TABLE IF EXISTS test_bind_fetch"))
+ printf("[002] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $rc = mysqli_query($link,"CREATE TABLE test_bind_fetch(c1 bigint default 5,
+ c2 bigint,
+ c3 bigint not NULL,
+ c4 bigint unsigned,
+ c5 bigint unsigned,
+ c6 bigint unsigned,
+ c7 bigint unsigned,
+ c8 bigint unsigned) ENGINE=" . $engine);
+ if (!$rc)
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $rc = mysqli_query($link, "INSERT INTO test_bind_fetch (c2,c3,c4,c5,c6,c7,c8) ".
+ "VALUES (-23,4.0,33333333333333,0,-333333333333,99.9,1234)");
+ if (!$rc)
+ printf("[004] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $stmt = mysqli_prepare($link, "SELECT * FROM test_bind_fetch");
+ mysqli_stmt_bind_result($stmt, $c1, $c2, $c3, $c4, $c5, $c6, $c7, $c8);
+ mysqli_stmt_execute($stmt);
+ $rc = mysqli_stmt_fetch($stmt);
+
+ if (mysqli_get_server_version($link) < 50000) {
+ // 4.1 is faulty and will return big number for $c6
+ if ($c6 == "18446743740376218283") {
+ $c6 = 0;
+ }
+ }
+ $c8 = 4567;// change this to test how mysqli/mysqlnd handles is_ref changing
+ $test = array($c1,$c2,$c3,$c4,$c5,$c6,$c7,$c8);
+
+ var_dump($test);
+
+ mysqli_stmt_close($stmt);
+
+ if (!mysqli_query($link, "DROP TABLE IF EXISTS test_bind_fetch_uint"))
+ printf("[005] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ $rc = mysqli_query($link, "CREATE TABLE test_bind_fetch_uint(c1 integer unsigned, c2 integer unsigned) ENGINE=" . $engine);
+ if (!$rc)
+ printf("[006] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, "INSERT INTO test_bind_fetch_uint (c1,c2) VALUES (20123456, 3123456789)"))
+ printf("[007] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $stmt = mysqli_prepare($link, "SELECT * FROM test_bind_fetch_uint");
+ mysqli_stmt_bind_result($stmt, $c1, $c2);
+ mysqli_stmt_execute($stmt);
+ $rc = mysqli_stmt_fetch($stmt);
+
+ echo $c1, "\n", $c2, "\n";
+
+ mysqli_stmt_close($stmt);
+ mysqli_query($link, "DROP TABLE IF EXISTS test_bind_fetch");
+ mysqli_query($link, "DROP TABLE IF EXISTS test_bind_fetch_uint");
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS test_bind_fetch"))
+ printf("[002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS test_bind_fetch_uint"))
+ printf("[002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+mysqli_close($link);
+?>
+--EXPECTF--
+array(8) {
+ [0]=>
+ int(5)
+ [1]=>
+ int(-23)
+ [2]=>
+ int(4)
+ [3]=>
+ %unicode|string%(14) "33333333333333"
+ [4]=>
+ int(0)
+ [5]=>
+ int(0)
+ [6]=>
+ int(100)
+ [7]=>
+ int(4567)
+}
+20123456
+3123456789
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/010.phpt b/ext/mysqli/tests/010.phpt
new file mode 100644
index 0000000..60ff8ea
--- /dev/null
+++ b/ext/mysqli/tests/010.phpt
@@ -0,0 +1,79 @@
+--TEST--
+mysqli fetch float values
+--INI--
+precision=12
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ /*** test mysqli_connect 127.0.0.1 ***/
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+ if (!mysqli_query($link, "SET sql_mode=''"))
+ printf("[001] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, "DROP TABLE IF EXISTS test_bind_fetch"))
+ printf("[002] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $rc = mysqli_query($link, "CREATE TABLE test_bind_fetch(c1 float(3),
+ c2 float,
+ c3 float unsigned,
+ c4 float,
+ c5 float,
+ c6 float,
+ c7 float(10) unsigned) ENGINE=" . $engine);
+ if (!$rc)
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+
+ mysqli_query($link, "INSERT INTO test_bind_fetch (c1,c2,c3,c4,c5,c6,c7) VALUES (3.1415926535,-0.000001, -5, 999999999999,
+ sin(0.6), 1.00000000000001, 888888888888888)");
+
+ $stmt = mysqli_prepare($link, "SELECT * FROM test_bind_fetch");
+ mysqli_stmt_bind_result($stmt, $c1, $c2, $c3, $c4, $c5, $c6, $c7);
+ mysqli_stmt_execute($stmt);
+ mysqli_stmt_fetch($stmt);
+
+ $test = array($c1,$c2,$c3,$c4,$c5,$c6,$c7);
+
+ var_dump($test);
+
+ mysqli_stmt_close($stmt);
+ mysqli_query($link, "DROP TABLE IF EXISTS test_bind_fetch");
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS test_bind_fetch"))
+ printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+mysqli_close($link);
+?>
+--EXPECT--
+array(7) {
+ [0]=>
+ float(3.14159274101)
+ [1]=>
+ float(-9.99999997475E-7)
+ [2]=>
+ float(0)
+ [3]=>
+ float(999999995904)
+ [4]=>
+ float(0.564642488956)
+ [5]=>
+ float(1)
+ [6]=>
+ float(8.88888914608E+14)
+}
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/011.phpt b/ext/mysqli/tests/011.phpt
new file mode 100644
index 0000000..db03aba
--- /dev/null
+++ b/ext/mysqli/tests/011.phpt
@@ -0,0 +1,78 @@
+--TEST--
+mysqli fetch mixed values
+--INI--
+precision=12
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ /*** test mysqli_connect 127.0.0.1 ***/
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+ if (!mysqli_query($link, "DROP TABLE IF EXISTS test_bind_result"))
+ printf("[001] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $rc = mysqli_query($link, "CREATE TABLE test_bind_result(c1 tinyint, c2 smallint,
+ c3 int, c4 bigint,
+ c5 float, c6 double,
+ c7 varbinary(10),
+ c8 varchar(50)) ENGINE=" . $engine);
+ if (!$rc)
+ printf("[002] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $rc = mysqli_query($link,"INSERT INTO test_bind_result VALUES(19,2999,3999,4999999,
+ 2345.6,5678.89563,
+ 'foobar','mysql rulez')");
+ if (!$rc)
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $stmt = mysqli_prepare($link, "SELECT * FROM test_bind_result");
+ mysqli_stmt_bind_result($stmt, $c1, $c2, $c3, $c4, $c5, $c6, $c7, $c8);
+ mysqli_stmt_execute($stmt);
+ mysqli_stmt_fetch($stmt);
+
+ $test = array($c1,$c2,$c3,$c4,$c5,$c6,$c7,$c8);
+
+ var_dump($test);
+
+ mysqli_stmt_close($stmt);
+ mysqli_query($link, "DROP TABLE IF EXISTS test_bind_result");
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS test_bind_result"))
+ printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+mysqli_close($link);
+?>
+--EXPECTF--
+array(8) {
+ [0]=>
+ int(19)
+ [1]=>
+ int(2999)
+ [2]=>
+ int(3999)
+ [3]=>
+ int(4999999)
+ [4]=>
+ float(2345.60009766)
+ [5]=>
+ float(5678.89563)
+ [6]=>
+ string(6) "foobar"
+ [7]=>
+ %unicode|string%(11) "mysql rulez"
+}
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/012.phpt b/ext/mysqli/tests/012.phpt
new file mode 100644
index 0000000..7cc34b0
--- /dev/null
+++ b/ext/mysqli/tests/012.phpt
@@ -0,0 +1,77 @@
+--TEST--
+mysqli fetch mixed values 2
+--INI--
+precision=12
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ /*** test mysqli_connect 127.0.0.1 ***/
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+ if (!mysqli_query($link, "DROP TABLE IF EXISTS test_bind_result"))
+ printf("[001] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $rc = mysqli_query($link, "CREATE TABLE test_bind_result(c1 tinyint, c2 smallint,
+ c3 int, c4 bigint,
+ c5 float, c6 double,
+ c7 varbinary(10),
+ c8 varchar(10)) ENGINE=" . $engine);
+ if (!$rc)
+ printf("[002] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, "INSERT INTO test_bind_result VALUES(120,2999,3999,54,
+ 2.6,58.89,
+ '206','6.7')"))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $stmt = mysqli_prepare($link, "SELECT * FROM test_bind_result");
+ mysqli_stmt_bind_result($stmt, $c1, $c2, $c3, $c4, $c5, $c6, $c7, $c8);
+ mysqli_stmt_execute($stmt);
+ mysqli_stmt_fetch($stmt);
+
+ $test = array($c1,$c2,$c3,$c4,$c5,$c6,$c7,$c8);
+
+ var_dump($test);
+
+ mysqli_stmt_close($stmt);
+ mysqli_query($link, "DROP TABLE IF EXISTS test_bind_result");
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS test_bind_result"))
+ printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+mysqli_close($link);
+?>
+--EXPECTF--
+array(8) {
+ [0]=>
+ int(120)
+ [1]=>
+ int(2999)
+ [2]=>
+ int(3999)
+ [3]=>
+ int(54)
+ [4]=>
+ float(2.59999990463)
+ [5]=>
+ float(58.89)
+ [6]=>
+ string(3) "206"
+ [7]=>
+ %unicode|string%(3) "6.7"
+}
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/013.phpt b/ext/mysqli/tests/013.phpt
new file mode 100644
index 0000000..6d75bde
--- /dev/null
+++ b/ext/mysqli/tests/013.phpt
@@ -0,0 +1,72 @@
+--TEST--
+mysqli fetch mixed / mysql_query (may fail when using 4.1 library with 5.x server)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ /*** test mysqli_connect 127.0.0.1 ***/
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+ if (!mysqli_query($link, "DROP TABLE IF EXISTS test_bind_result"))
+ printf("[001] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $rc = mysqli_query($link, "CREATE TABLE test_bind_result(c1 tinyint, c2 smallint,
+ c3 int, c4 bigint,
+ c5 decimal(4,2), c6 double,
+ c7 varbinary(10),
+ c8 varchar(10)) ENGINE=" . $engine);
+ if (!$rc)
+ printf("[002] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, "INSERT INTO test_bind_result VALUES(120,2999,3999,54,
+ 2.6,58.89,
+ '206','6.7')"))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $stmt = mysqli_prepare($link, "SELECT * FROM test_bind_result");
+
+ $c = array(0,0,0,0,0,0,0,0);
+ $b_res= mysqli_stmt_bind_result($stmt, $c[0], $c[1], $c[2], $c[3], $c[4], $c[5], $c[6], $c[7]);
+ mysqli_stmt_execute($stmt);
+ mysqli_stmt_fetch($stmt);
+ mysqli_stmt_fetch($stmt);
+ mysqli_stmt_close($stmt);
+
+ $result = mysqli_query($link, "select * from test_bind_result");
+ $d = mysqli_fetch_row($result);
+ mysqli_free_result($result);
+
+ $test = "";
+ for ($i=0; $i < count($c); $i++)
+ $test .= ($c[$i] == $d[$i]) ? "1" : "0";
+ if ($test == "11111111")
+ echo "ok\n";
+ else if ($b_res == FALSE && mysqli_get_client_version() > 40100 && mysqli_get_client_version() < 50000 &&
+ mysqli_get_server_version($link) > 50000)
+ echo "error (4.1 library with 5.x server)";
+ else
+ echo "error";
+
+ mysqli_query($link, "DROP TABLE IF EXISTS test_bind_result");
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS test_bind_result"))
+ printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+mysqli_close($link);
+?>
+--EXPECTF--
+ok
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/014.phpt b/ext/mysqli/tests/014.phpt
new file mode 100644
index 0000000..da6a005
--- /dev/null
+++ b/ext/mysqli/tests/014.phpt
@@ -0,0 +1,97 @@
+--TEST--
+mysqli autocommit/commit/rollback
+--SKIPIF--
+<?php
+ require_once('skipif.inc');
+ require_once('skipifconnectfailure.inc');
+ require_once("connect.inc");
+
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+ if (!$link)
+ die(sprintf("Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error()));
+
+ if (!have_innodb($link))
+ die(sprintf("Needs InnoDB support, [%d] %s", $link->errno, $link->error));
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+ if (!mysqli_autocommit($link, TRUE))
+ printf("[001] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, "DROP TABLE IF EXISTS test"))
+ printf("[002] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, "CREATE TABLE test(a int, b varchar(10)) engine=InnoDB"))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, "INSERT INTO test VALUES (1, 'foobar')"))
+ printf("[004] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_autocommit($link, FALSE))
+ printf("[005] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, "DELETE FROM test"))
+ printf("[006] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, "INSERT INTO test VALUES (2, 'egon')"))
+ printf("[007] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_rollback($link))
+ printf("[008] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$result = mysqli_query($link, "SELECT * FROM test"))
+ printf("[009] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ printf("Num_of_rows=%d\n", mysqli_num_rows($result));
+ if (!$row = mysqli_fetch_row($result))
+ printf("[010] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ mysqli_free_result($result);
+
+ var_dump($row);
+
+ if (!mysqli_query($link, "DELETE FROM test"))
+ printf("[011] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, "INSERT INTO test VALUES (2, 'egon')"))
+ printf("[012] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_commit($link))
+ printf("[012] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$result = mysqli_query($link, "SELECT * FROM test"))
+ printf("[013] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$row = mysqli_fetch_row($result))
+ printf("[014] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ mysqli_free_result($result);
+
+ var_dump($row);
+
+ mysqli_query($link, "DROP TABLE IF EXISTS test");
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Num_of_rows=1
+array(2) {
+ [0]=>
+ %unicode|string%(1) "1"
+ [1]=>
+ %unicode|string%(6) "foobar"
+}
+array(2) {
+ [0]=>
+ %unicode|string%(1) "2"
+ [1]=>
+ %unicode|string%(4) "egon"
+}
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/015.phpt b/ext/mysqli/tests/015.phpt
new file mode 100644
index 0000000..c671ad6
--- /dev/null
+++ b/ext/mysqli/tests/015.phpt
@@ -0,0 +1,94 @@
+--TEST--
+mysqli autocommit/commit/rollback with innodb
+--SKIPIF--
+<?php
+ require_once('skipif.inc');
+ require_once('skipifconnectfailure.inc');
+
+ require_once('connect.inc');
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ die(sprintf("Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error()));
+
+ if (!have_innodb($link))
+ die(sprintf("Needs InnoDB support, [%d] %s", $link->errno, $link->error));
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+ if (!$link)
+ printf("[001] Cannot connect, [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+ if (!mysqli_select_db($link, $db))
+ printf("[002] Cannot select DB '%s', [%d] %s\n", $db,
+ mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_autocommit($link, TRUE))
+ printf("[003] Cannot turn on autocommit mode, [%d] %s\n",
+ mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link,"DROP TABLE IF EXISTS test") ||
+ !mysqli_query($link,"CREATE TABLE test(a int, b varchar(10)) Engine=InnoDB") ||
+ !mysqli_query($link, "INSERT INTO test VALUES (1, 'foobar')"))
+ printf("[004] Cannot create test data, [%d] %s\n",
+ mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_autocommit($link, FALSE))
+ printf("[005] Cannot turn off autocommit mode, [%d] %s\n",
+ mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, "DELETE FROM test") ||
+ !mysqli_query($link, "INSERT INTO test VALUES (2, 'egon')"))
+ printf("[006] Cannot modify test data, [%d] %s\n",
+ mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_rollback($link))
+ printf("[007] Cannot call rollback, [%d] %s\n",
+ mysqli_errno($link), mysqli_error($link));
+
+ $result = mysqli_query($link, "SELECT SQL_NO_CACHE * FROM test");
+ if (!$result)
+ printf("[008] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ $row = mysqli_fetch_row($result);
+ mysqli_free_result($result);
+
+ var_dump($row);
+
+ if (!mysqli_query($link, "DELETE FROM test") ||
+ !mysqli_query($link, "INSERT INTO test VALUES (2, 'egon')"))
+ printf("[009] Cannot modify test data, [%d] %s\n",
+ mysqli_errno($link), mysqli_error($link));
+
+ mysqli_commit($link);
+
+ $result = mysqli_query($link, "SELECT * FROM test");
+ if (!$result)
+ printf("[010] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ $row = mysqli_fetch_row($result);
+ mysqli_free_result($result);
+
+ var_dump($row);
+
+ mysqli_query($link, "DROP TABLE IF EXISTS test");
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+array(2) {
+ [0]=>
+ %unicode|string%(1) "1"
+ [1]=>
+ %unicode|string%(6) "foobar"
+}
+array(2) {
+ [0]=>
+ %unicode|string%(1) "2"
+ [1]=>
+ %unicode|string%(4) "egon"
+}
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/016.phpt b/ext/mysqli/tests/016.phpt
new file mode 100644
index 0000000..8e1ffe6
--- /dev/null
+++ b/ext/mysqli/tests/016.phpt
@@ -0,0 +1,33 @@
+--TEST--
+mysqli fetch user variable
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ /*** test mysqli_connect 127.0.0.1 ***/
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+ if (!mysqli_query($link, "SET @dummy='foobar'"))
+ printf("[001] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$stmt = mysqli_prepare($link, "SELECT @dummy"))
+ printf("[002] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ mysqli_stmt_bind_result($stmt, $dummy);
+ mysqli_stmt_execute($stmt);
+ mysqli_stmt_fetch($stmt);
+
+ var_dump($dummy);
+
+ mysqli_stmt_close($stmt);
+ mysqli_close($link);
+ print "done!";
+?>
+--EXPECTF--
+%unicode|string%(6) "foobar"
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/017.phpt b/ext/mysqli/tests/017.phpt
new file mode 100644
index 0000000..082202f
--- /dev/null
+++ b/ext/mysqli/tests/017.phpt
@@ -0,0 +1,43 @@
+--TEST--
+mysqli fetch functions
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ /*** test mysqli_connect 127.0.0.1 ***/
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+ if (!$stmt = mysqli_prepare($link, "SELECT md5('bar'), database(), 'foo'"))
+ printf("[001] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ mysqli_stmt_bind_result($stmt, $c0, $c1, $c2);
+ mysqli_stmt_execute($stmt);
+
+ mysqli_stmt_fetch($stmt);
+ mysqli_stmt_close($stmt);
+
+ $test = array($c0, $c1, $c2);
+ if ($c1 !== $db) {
+ echo "Different data\n";
+ }
+
+ var_dump($test);
+ mysqli_close($link);
+ print "done!";
+?>
+--EXPECTF--
+array(3) {
+ [0]=>
+ string(32) "37b51d194a7513e45b56f6524f2d51f2"
+ [1]=>
+ %unicode|string%(%d) "%s"
+ [2]=>
+ %unicode|string%(3) "foo"
+}
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/018.phpt b/ext/mysqli/tests/018.phpt
new file mode 100644
index 0000000..d5466e2
--- /dev/null
+++ b/ext/mysqli/tests/018.phpt
@@ -0,0 +1,33 @@
+--TEST--
+mysqli fetch system variables
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ /*** test mysqli_connect 127.0.0.1 ***/
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+ if (!mysqli_query($link, "SET AUTOCOMMIT=0"))
+ printf("[001] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$stmt = mysqli_prepare($link, "SELECT @@autocommit"))
+ printf("[001] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ mysqli_stmt_bind_result($stmt, $c0);
+ mysqli_stmt_execute($stmt);
+
+ mysqli_stmt_fetch($stmt);
+
+ var_dump($c0);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--EXPECT--
+int(0)
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/019.phpt b/ext/mysqli/tests/019.phpt
new file mode 100644
index 0000000..5e6aac0
--- /dev/null
+++ b/ext/mysqli/tests/019.phpt
@@ -0,0 +1,94 @@
+--TEST--
+mysqli fetch (bind_param + bind_result)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ /*** test mysqli_connect 127.0.0.1 ***/
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+ if (!mysqli_query($link, "DROP TABLE IF EXISTS insert_read"))
+ printf("[001] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $rc = mysqli_query($link,"CREATE TABLE insert_read(col1 tinyint, col2 smallint,
+ col3 int, col4 bigint,
+ col5 float, col6 double,
+ col7 date, col8 time,
+ col9 varbinary(10),
+ col10 varchar(50),
+ col11 char(20)) ENGINE=" . $engine);
+ if (!$rc)
+ printf("[002] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$stmt = mysqli_prepare($link, "INSERT INTO insert_read(col1,col10, col11, col6) VALUES (?,?,?,?)"))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ mysqli_stmt_bind_param($stmt, "issd", $c1, $c2, $c3, $c4);
+
+ $c1 = 1;
+ $c2 = "foo";
+ $c3 = "foobar";
+ $c4 = 3.14;
+
+ mysqli_stmt_execute($stmt);
+ mysqli_stmt_close($stmt);
+
+ if (!$stmt = mysqli_prepare($link, "SELECT col1, col2, col3, col4, col5, col6, col7, col8, col9, col10, col11 FROM insert_read"))
+ printf("[004] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ mysqli_stmt_bind_result($stmt, $c1, $c2, $c3, $c4, $c5, $c6, $c7, $c8, $c9, $c10, $c11);
+ mysqli_stmt_execute($stmt);
+
+ mysqli_stmt_fetch($stmt);
+
+ $test = array($c1,$c2,$c3,$c4,$c5,$c6,$c7,$c8,$c9,$c10,$c11);
+
+ var_dump($test);
+
+ mysqli_stmt_close($stmt);
+ mysqli_query($link, "DROP TABLE IF EXISTS insert_read");
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS insert_read"))
+ printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+mysqli_close($link);
+?>
+--EXPECTF--
+array(11) {
+ [0]=>
+ int(1)
+ [1]=>
+ NULL
+ [2]=>
+ NULL
+ [3]=>
+ NULL
+ [4]=>
+ NULL
+ [5]=>
+ float(3.14)
+ [6]=>
+ NULL
+ [7]=>
+ NULL
+ [8]=>
+ NULL
+ [9]=>
+ %unicode|string%(3) "foo"
+ [10]=>
+ %unicode|string%(6) "foobar"
+}
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/020.phpt b/ext/mysqli/tests/020.phpt
new file mode 100644
index 0000000..6512cd8
--- /dev/null
+++ b/ext/mysqli/tests/020.phpt
@@ -0,0 +1,98 @@
+--TEST--
+mysqli bind_param/bind_result date
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ /*** test mysqli_connect 127.0.0.1 ***/
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+ mysqli_select_db($link, $db);
+ mysqli_query($link, "SET sql_mode=''");
+
+ mysqli_query($link,"DROP TABLE IF EXISTS test_bind_result");
+
+ $rc = @mysqli_query($link,"CREATE TABLE test_bind_result(
+ c1 date,
+ c2 time,
+ c3 timestamp(14),
+ c4 year,
+ c5 datetime,
+ c6 timestamp(4),
+ c7 timestamp(6))");
+
+ if (!$rc)
+ $rc = mysqli_query($link,"CREATE TABLE test_bind_result(
+ c1 date,
+ c2 time,
+ c3 timestamp,
+ c4 year,
+ c5 datetime,
+ c6 timestamp,
+ c7 timestamp)");
+
+ $stmt = mysqli_prepare($link, "INSERT INTO test_bind_result VALUES (?,?,?,?,?,?,?)");
+ mysqli_stmt_bind_param($stmt, "sssssss", $d1, $d2, $d3, $d4, $d5, $d6, $d7);
+
+ $d1 = "2002-01-02";
+ $d2 = "12:49:00";
+ $d3 = "2002-01-02 17:46:59";
+ $d4 = "2010";
+ $d5 = "2010-07-10";
+ $d6 = "2020";
+ $d7 = "1999-12-29";
+
+ mysqli_stmt_execute($stmt);
+ mysqli_stmt_close($stmt);
+
+ $stmt = mysqli_prepare($link, "SELECT c1, c2, c3, c4, c5, c6, c7 FROM test_bind_result");
+
+ mysqli_stmt_bind_result($stmt,$c1, $c2, $c3, $c4, $c5, $c6, $c7);
+
+ mysqli_stmt_execute($stmt);
+ mysqli_stmt_fetch($stmt);
+
+ $test = array($c1,$c2,$c3,$c4,$c5,$c6,$c7);
+
+ var_dump($test);
+
+ mysqli_stmt_close($stmt);
+ mysqli_query($link, "DROP TABLE IF EXISTS test_bind_result");
+ mysqli_close($link);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS test_bind_result"))
+ printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+mysqli_close($link);
+?>
+--EXPECTF--
+array(7) {
+ [0]=>
+ %s(10) "2002-01-02"
+ [1]=>
+ %s(8) "12:49:00"
+ [2]=>
+ %s(19) "2002-01-02 17:46:59"
+ [3]=>
+ int(2010)
+ [4]=>
+ %s(19) "2010-07-10 00:00:00"
+ [5]=>
+ %s(19) "0000-00-00 00:00:00"
+ [6]=>
+ %s(19) "1999-12-29 00:00:00"
+}
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/021.phpt b/ext/mysqli/tests/021.phpt
new file mode 100644
index 0000000..5ff58c0
--- /dev/null
+++ b/ext/mysqli/tests/021.phpt
@@ -0,0 +1,59 @@
+--TEST--
+mysqli bind_param+bind_result char/text
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ /*** test mysqli_connect 127.0.0.1 ***/
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+ mysqli_select_db($link, $db);
+
+ mysqli_query($link,"DROP TABLE IF EXISTS test_bind_fetch");
+ mysqli_query($link,"CREATE TABLE test_bind_fetch(c1 char(10), c2 text)");
+
+ $stmt = mysqli_prepare($link, "INSERT INTO test_bind_fetch VALUES (?,?)");
+ mysqli_stmt_bind_param($stmt, "ss", $q1, $q2);
+ $q1 = "1234567890";
+ $q2 = "this is a test";
+ mysqli_stmt_execute($stmt);
+ mysqli_stmt_close($stmt);
+
+ $stmt = mysqli_prepare($link, "SELECT * FROM test_bind_fetch");
+ mysqli_stmt_bind_result($stmt, $c1, $c2);
+ mysqli_stmt_execute($stmt);
+ mysqli_stmt_fetch($stmt);
+
+ $test = array($c1,$c2);
+
+ var_dump($test);
+
+ mysqli_stmt_close($stmt);
+ mysqli_query($link, "DROP TABLE IF EXISTS test_bind_fetch");
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS test_bind_fetch"))
+ printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+mysqli_close($link);
+?>
+--EXPECTF--
+array(2) {
+ [0]=>
+ %unicode|string%(10) "1234567890"
+ [1]=>
+ %unicode|string%(14) "this is a test"
+}
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/022.phpt b/ext/mysqli/tests/022.phpt
new file mode 100644
index 0000000..9cb71c0
--- /dev/null
+++ b/ext/mysqli/tests/022.phpt
@@ -0,0 +1,64 @@
+--TEST--
+mysqli bind_param/bind_result char/text long
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ /*** test mysqli_connect 127.0.0.1 ***/
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+ mysqli_select_db($link, $db);
+
+ mysqli_query($link,"DROP TABLE IF EXISTS test_bind_fetch");
+ mysqli_query($link,"CREATE TABLE test_bind_fetch(c1 char(10), c2 text)");
+
+
+ $stmt = mysqli_prepare($link, "INSERT INTO test_bind_fetch VALUES (?,?)");
+ mysqli_stmt_bind_param($stmt, "ss", $a1, $a2);
+
+ $a1 = "1234567890";
+ $a2 = str_repeat("A1", 32000);
+
+ mysqli_stmt_execute($stmt);
+ mysqli_stmt_close($stmt);
+
+ $stmt = mysqli_prepare($link, "SELECT * FROM test_bind_fetch");
+ mysqli_stmt_bind_result($stmt, $c1, $c2);
+ mysqli_stmt_execute($stmt);
+ mysqli_stmt_fetch($stmt);
+
+ $test[] = $c1;
+ $test[] = ($a2 == $c2) ? "32K String ok" : "32K String failed";
+
+ var_dump($test);
+
+ mysqli_stmt_close($stmt);
+ mysqli_query($link, "DROP TABLE IF EXISTS test_bind_fetch");
+ mysqli_close($link);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS test_bind_fetch"))
+ printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+mysqli_close($link);
+?>
+--EXPECTF--
+array(2) {
+ [0]=>
+ %unicode|string%(10) "1234567890"
+ [1]=>
+ %s(13) "32K String ok"
+}
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/023.phpt b/ext/mysqli/tests/023.phpt
new file mode 100644
index 0000000..2528519
--- /dev/null
+++ b/ext/mysqli/tests/023.phpt
@@ -0,0 +1,83 @@
+--TEST--
+mysqli bind_param/bind_prepare fetch long values
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ /*** test mysqli_connect 127.0.0.1 ***/
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+ mysqli_select_db($link, $db);
+ mysqli_query($link, "SET sql_mode=''");
+
+ mysqli_query($link,"DROP TABLE IF EXISTS test_bind_fetch");
+ mysqli_query($link,"CREATE TABLE test_bind_fetch(c1 int unsigned,
+ c2 int unsigned,
+ c3 int,
+ c4 int,
+ c5 int,
+ c6 int unsigned,
+ c7 int)");
+
+ $stmt = mysqli_prepare($link, "INSERT INTO test_bind_fetch VALUES (?,?,?,?,?,?,?)");
+ mysqli_stmt_bind_param($stmt, "iiiiiii", $c1,$c2,$c3,$c4,$c5,$c6,$c7);
+ $c1 = -23;
+ $c2 = 35999;
+ $c3 = NULL;
+ $c4 = -500;
+ $c5 = -9999999;
+ $c6 = -0;
+ $c7 = 0;
+
+ mysqli_stmt_execute($stmt);
+ mysqli_stmt_close($stmt);
+
+ $stmt = mysqli_prepare($link, "SELECT * FROM test_bind_fetch");
+ mysqli_stmt_bind_result($stmt, $c1, $c2, $c3, $c4, $c5, $c6, $c7);
+ mysqli_stmt_execute($stmt);
+ mysqli_stmt_fetch($stmt);
+
+ $test = array($c1,$c2,$c3,$c4,$c5,$c6,$c7);
+
+ var_dump($test);
+
+ mysqli_stmt_close($stmt);
+ mysqli_query($link, "DROP TABLE IF EXISTS test_bind_fetch");
+ mysqli_close($link);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS test_bind_fetch"))
+ printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+mysqli_close($link);
+?>
+--EXPECT--
+array(7) {
+ [0]=>
+ int(0)
+ [1]=>
+ int(35999)
+ [2]=>
+ NULL
+ [3]=>
+ int(-500)
+ [4]=>
+ int(-9999999)
+ [5]=>
+ int(0)
+ [6]=>
+ int(0)
+}
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/024.phpt b/ext/mysqli/tests/024.phpt
new file mode 100644
index 0000000..893ca0d
--- /dev/null
+++ b/ext/mysqli/tests/024.phpt
@@ -0,0 +1,83 @@
+--TEST--
+mysqli bind_param/bind_result short values
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ /*** test mysqli_connect 127.0.0.1 ***/
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+ mysqli_select_db($link, $db);
+ mysqli_query($link, "SET sql_mode=''");
+
+ mysqli_query($link,"DROP TABLE IF EXISTS test_bind_fetch");
+ mysqli_query($link,"CREATE TABLE test_bind_fetch(c1 smallint unsigned,
+ c2 smallint unsigned,
+ c3 smallint,
+ c4 smallint,
+ c5 smallint,
+ c6 smallint unsigned,
+ c7 smallint)");
+
+ $stmt = mysqli_prepare($link, "INSERT INTO test_bind_fetch VALUES (?,?,?,?,?,?,?)");
+ mysqli_stmt_bind_param($stmt, "iiiiiii", $c1,$c2,$c3,$c4,$c5,$c6,$c7);
+
+ $c1 = -23;
+ $c2 = 35999;
+ $c3 = NULL;
+ $c4 = -500;
+ $c5 = -9999999;
+ $c6 = -0;
+ $c7 = 0;
+
+ mysqli_stmt_execute($stmt);
+ mysqli_stmt_close($stmt);
+
+ $stmt = mysqli_prepare($link, "SELECT * FROM test_bind_fetch");
+ mysqli_stmt_bind_result($stmt, $c1, $c2, $c3, $c4, $c5, $c6, $c7);
+ mysqli_stmt_execute($stmt);
+ mysqli_stmt_fetch($stmt);
+
+ $test = array($c1,$c2,$c3,$c4,$c5,$c6,$c7);
+
+ var_dump($test);
+
+ mysqli_stmt_close($stmt);
+ mysqli_query($link, "DROP TABLE IF EXISTS test_bind_fetch");
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS test_bind_fetch"))
+ printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+mysqli_close($link);
+?>
+--EXPECT--
+array(7) {
+ [0]=>
+ int(0)
+ [1]=>
+ int(35999)
+ [2]=>
+ NULL
+ [3]=>
+ int(-500)
+ [4]=>
+ int(-32768)
+ [5]=>
+ int(0)
+ [6]=>
+ int(0)
+}
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/025.phpt b/ext/mysqli/tests/025.phpt
new file mode 100644
index 0000000..937d624
--- /dev/null
+++ b/ext/mysqli/tests/025.phpt
@@ -0,0 +1,88 @@
+--TEST--
+mysqli bind_param/bind_result tinyint values
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ /*** test mysqli_connect 127.0.0.1 ***/
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+ mysqli_select_db($link, $db);
+ mysqli_query($link, "SET sql_mode=''");
+
+ mysqli_query($link,"DROP TABLE IF EXISTS test_bind_fetch");
+ mysqli_query($link,"CREATE TABLE test_bind_fetch(c1 tinyint,
+ c2 tinyint unsigned,
+ c3 tinyint not NULL,
+ c4 tinyint,
+ c5 tinyint,
+ c6 tinyint unsigned,
+ c7 tinyint)");
+
+ $stmt = mysqli_prepare ($link, "INSERT INTO test_bind_fetch VALUES(?,?,?,?,?,?,?)");
+ mysqli_stmt_bind_param($stmt, "iiiiiii", $c1,$c2,$c3,$c4,$c5,$c6,$c7);
+
+ $c1 = -23;
+ $c2 = 300;
+ $c3 = 0;
+ $c4 = -100;
+ $c5 = -127;
+ $c6 = 30;
+ $c7 = 0;
+
+ mysqli_stmt_execute($stmt);
+ mysqli_stmt_close($stmt);
+
+ mysqli_query($link, "INSERT INTO test_bind_fetch VALUES (-23,300,0,-100,-127,+30,0)");
+
+ $c1 = $c2 = $c3 = $c4 = $c5 = $c6 = $c7 = NULL;
+
+ $stmt = mysqli_prepare($link, "SELECT * FROM test_bind_fetch");
+ mysqli_stmt_bind_result($stmt, $c1, $c2, $c3, $c4, $c5, $c6, $c7);
+ mysqli_stmt_execute($stmt);
+ mysqli_stmt_fetch($stmt);
+
+ $test = array($c1,$c2,$c3,$c4,$c5,$c6,$c7);
+
+ var_dump($test);
+
+ mysqli_stmt_close($stmt);
+ mysqli_query($link, "DROP TABLE IF EXISTS test_bind_fetch");
+ mysqli_close($link);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS test_bind_fetch"))
+ printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+mysqli_close($link);
+?>
+--EXPECT--
+array(7) {
+ [0]=>
+ int(-23)
+ [1]=>
+ int(255)
+ [2]=>
+ int(0)
+ [3]=>
+ int(-100)
+ [4]=>
+ int(-127)
+ [5]=>
+ int(30)
+ [6]=>
+ int(0)
+}
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/026.phpt b/ext/mysqli/tests/026.phpt
new file mode 100644
index 0000000..47d763a
--- /dev/null
+++ b/ext/mysqli/tests/026.phpt
@@ -0,0 +1,65 @@
+--TEST--
+mysqli bind_param/bind_result with send_long_data
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ /*** test mysqli_connect 127.0.0.1 ***/
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+ mysqli_select_db($link, $db);
+ mysqli_query($link, "SET sql_mode=''");
+
+ mysqli_query($link,"DROP TABLE IF EXISTS test_bind_fetch");
+ mysqli_query($link,"CREATE TABLE test_bind_fetch(c1 varchar(10), c2 text)");
+
+ $stmt = mysqli_prepare ($link, "INSERT INTO test_bind_fetch VALUES (?,?)");
+ mysqli_stmt_bind_param($stmt, "sb", $c1, $c2);
+
+ $c1 = "Hello World";
+
+ mysqli_stmt_send_long_data($stmt, 1, "This is the first sentence.");
+ mysqli_stmt_send_long_data($stmt, 1, " And this is the second sentence.");
+ mysqli_stmt_send_long_data($stmt, 1, " And finally this is the last sentence.");
+
+ mysqli_stmt_execute($stmt);
+ mysqli_stmt_close($stmt);
+
+ $stmt = mysqli_prepare($link, "SELECT * FROM test_bind_fetch");
+ mysqli_stmt_bind_result($stmt, $d1, $d2);
+ mysqli_stmt_execute($stmt);
+ mysqli_stmt_fetch($stmt);
+
+ $test = array($d1,$d2);
+
+ var_dump($test);
+
+ mysqli_stmt_close($stmt);
+ mysqli_query($link, "DROP TABLE IF EXISTS test_bind_fetch");
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS test_bind_fetch"))
+ printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+mysqli_close($link);
+?>
+--EXPECTF--
+array(2) {
+ [0]=>
+ %unicode|string%(10) "Hello Worl"
+ [1]=>
+ %unicode|string%(99) "This is the first sentence. And this is the second sentence. And finally this is the last sentence."
+}
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/027.phpt b/ext/mysqli/tests/027.phpt
new file mode 100644
index 0000000..69233d6
--- /dev/null
+++ b/ext/mysqli/tests/027.phpt
@@ -0,0 +1,24 @@
+--TEST--
+function test: mysqli_stat
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ /*** test mysqli_connect 127.0.0.1 ***/
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+ $status = mysqli_stat($link);
+
+ var_dump(strlen($status) > 0);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--EXPECT--
+bool(true)
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/028.phpt b/ext/mysqli/tests/028.phpt
new file mode 100644
index 0000000..af453dd
--- /dev/null
+++ b/ext/mysqli/tests/028.phpt
@@ -0,0 +1,24 @@
+--TEST--
+function test: mysqli_character_set_name
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ /*** test mysqli_connect 127.0.0.1 ***/
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+ $cset = substr(mysqli_character_set_name($link),0,6);
+
+ var_dump($cset);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--EXPECTF--
+%unicode|string%(%d) "%s"
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/029.phpt b/ext/mysqli/tests/029.phpt
new file mode 100644
index 0000000..9364206
--- /dev/null
+++ b/ext/mysqli/tests/029.phpt
@@ -0,0 +1,42 @@
+--TEST--
+function test: mysqli_affected_rows
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ /*** test mysqli_connect 127.0.0.1 ***/
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+ mysqli_select_db($link, $db);
+
+ mysqli_query($link, "DROP TABLE IF EXISTS general_test");
+ mysqli_query($link, "CREATE TABLE general_test (a INT)");
+ mysqli_query($link, "INSERT INTO general_test VALUES (1),(2),(3)");
+
+ $afc = mysqli_affected_rows($link);
+
+ var_dump($afc);
+
+ mysqli_query($link, "DROP TABLE IF EXISTS general_test");
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS general_test"))
+ printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+mysqli_close($link);
+?>
+--EXPECT--
+int(3)
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/030.phpt b/ext/mysqli/tests/030.phpt
new file mode 100644
index 0000000..c4b1710
--- /dev/null
+++ b/ext/mysqli/tests/030.phpt
@@ -0,0 +1,30 @@
+--TEST--
+function test: mysqli_errno
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ /*** test mysqli_connect 127.0.0.1 ***/
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+ $errno = mysqli_errno($link);
+ var_dump($errno);
+
+ mysqli_select_db($link, $db);
+
+ mysqli_query($link, "SELECT * FROM non_exisiting_table");
+ $errno = mysqli_errno($link);
+
+ var_dump($errno);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--EXPECT--
+int(0)
+int(1146)
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/031.phpt b/ext/mysqli/tests/031.phpt
new file mode 100644
index 0000000..9b8c720
--- /dev/null
+++ b/ext/mysqli/tests/031.phpt
@@ -0,0 +1,30 @@
+--TEST--
+function test: mysqli_error
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ /*** test mysqli_connect 127.0.0.1 ***/
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+ $error = mysqli_error($link);
+ var_dump($error);
+
+ mysqli_select_db($link, $db);
+
+ mysqli_query($link, "SELECT * FROM non_exisiting_table");
+ $error = mysqli_error($link);
+
+ var_dump($error);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--EXPECTF--
+%unicode|string%(0) ""
+%unicode|string%(%d) "%s"
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/032.phpt b/ext/mysqli/tests/032.phpt
new file mode 100644
index 0000000..5fcd548
--- /dev/null
+++ b/ext/mysqli/tests/032.phpt
@@ -0,0 +1,42 @@
+--TEST--
+function test: mysqli_info
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ /*** test mysqli_connect 127.0.0.1 ***/
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+ mysqli_select_db($link, $db);
+
+ mysqli_query($link, "DROP TABLE IF EXISTS general_test");
+ mysqli_query($link, "CREATE TABLE general_test (a INT)");
+ mysqli_query($link, "INSERT INTO general_test VALUES (1),(2),(3)");
+
+ $afc = mysqli_info($link);
+
+ var_dump($afc);
+
+ mysqli_query($link, "DROP TABLE IF EXISTS general_test");
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS general_test"))
+ printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+mysqli_close($link);
+?>
+--EXPECTF--
+%unicode|string%(38) "Records: 3 Duplicates: 0 Warnings: 0"
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/033.phpt b/ext/mysqli/tests/033.phpt
new file mode 100644
index 0000000..b499bd7
--- /dev/null
+++ b/ext/mysqli/tests/033.phpt
@@ -0,0 +1,25 @@
+--TEST--
+function test: mysqli_get_host_info
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ /*** test mysqli_connect 127.0.0.1 ***/
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+ $hinfo = mysqli_get_host_info($link);
+
+ var_dump(str_replace('/','', $hinfo));
+
+ mysqli_close($link);
+ print "done!";
+?>
+--EXPECTF--
+%unicode|string%(%d) "%s via %s"
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/034.phpt b/ext/mysqli/tests/034.phpt
new file mode 100644
index 0000000..3fda560
--- /dev/null
+++ b/ext/mysqli/tests/034.phpt
@@ -0,0 +1,25 @@
+--TEST--
+function test: mysqli_get_proto_info
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ /*** test mysqli_connect 127.0.0.1 ***/
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+ $pinfo = mysqli_get_proto_info($link);
+
+ var_dump($pinfo);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--EXPECT--
+int(10)
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/035.phpt b/ext/mysqli/tests/035.phpt
new file mode 100644
index 0000000..7b18e02
--- /dev/null
+++ b/ext/mysqli/tests/035.phpt
@@ -0,0 +1,24 @@
+--TEST--
+function test: mysqli_get_server_info
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ /*** test mysqli_connect 127.0.0.1 ***/
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+ $sinfo = substr(mysqli_get_server_info($link),0,1);
+
+ var_dump(strlen($sinfo));
+
+ mysqli_close($link);
+ print "done!";
+?>
+--EXPECT--
+int(1)
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/036.phpt b/ext/mysqli/tests/036.phpt
new file mode 100644
index 0000000..b0d259c
--- /dev/null
+++ b/ext/mysqli/tests/036.phpt
@@ -0,0 +1,63 @@
+--TEST--
+function test: mysqli_insert_id()
+--SKIPIF--
+<?php
+ if (PHP_INT_SIZE == 8) {
+ echo 'skip test valid only for 32bit systems';
+ exit;
+ }
+ require_once('skipif.inc');
+ require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ /*** test mysqli_connect 127.0.0.1 ***/
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+ mysqli_select_db($link, $db);
+
+ mysqli_query($link, "DROP TABLE IF EXISTS t036");
+ mysqli_query($link, "CREATE TABLE t036 (a bigint not null auto_increment primary key, b varchar(10)) ENGINE = " . $engine);
+
+ mysqli_query($link, "INSERT INTO t036 (b) VALUES ('foo1')");
+ $test[] = mysqli_insert_id($link);
+
+ /* we have to insert more values, cause lexer sets auto_increment to max_int
+ see mysql bug #54. So we don't check for the value, only for type (which must
+ be type string)
+ */
+
+ mysqli_query($link, "ALTER TABLE t036 AUTO_INCREMENT=9999999999999998");
+ mysqli_query($link, "INSERT INTO t036 (b) VALUES ('foo2')");
+ mysqli_query($link, "INSERT INTO t036 (b) VALUES ('foo3')");
+ mysqli_query($link, "INSERT INTO t036 (b) VALUES ('foo4')");
+ $x = mysqli_insert_id($link);
+ $test[] = is_string($x);
+
+ var_dump($test);
+
+ mysqli_query($link, "DROP TABLE IF EXISTS t036");
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS t036"))
+ printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+mysqli_close($link);
+?>
+--EXPECT--
+array(2) {
+ [0]=>
+ int(1)
+ [1]=>
+ bool(true)
+}
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/037.phpt b/ext/mysqli/tests/037.phpt
new file mode 100644
index 0000000..03d5d55
--- /dev/null
+++ b/ext/mysqli/tests/037.phpt
@@ -0,0 +1,53 @@
+--TEST--
+function test: mysqli_field_count()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+
+ require_once("connect.inc");
+
+ /*** test mysqli_connect 127.0.0.1 ***/
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+ mysqli_select_db($link, $db);
+
+ mysqli_query($link, "DROP TABLE IF EXISTS test_result");
+
+ mysqli_query($link, "CREATE TABLE test_result (a int, b varchar(10)) ENGINE = " . $engine);
+
+ mysqli_query($link, "INSERT INTO test_result VALUES (1, 'foo')");
+ $ir[] = mysqli_field_count($link);
+
+ mysqli_real_query($link, "SELECT * FROM test_result");
+ $ir[] = mysqli_field_count($link);
+
+
+ var_dump($ir);
+
+ mysqli_query($link, "DROP TABLE IF EXISTS test_result");
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS test_result"))
+ printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+mysqli_close($link);
+?>
+--EXPECT--
+array(2) {
+ [0]=>
+ int(0)
+ [1]=>
+ int(2)
+}
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/038.phpt b/ext/mysqli/tests/038.phpt
new file mode 100644
index 0000000..45b724c
--- /dev/null
+++ b/ext/mysqli/tests/038.phpt
@@ -0,0 +1,47 @@
+--TEST--
+function test: mysqli_num_fields()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ /*** test mysqli_connect 127.0.0.1 ***/
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+ mysqli_select_db($link, $db);
+
+ mysqli_query($link, "DROP TABLE IF EXISTS test_result");
+
+ mysqli_query($link, "CREATE TABLE test_result (a int, b varchar(10)) ENGINE = " . $engine);
+
+ mysqli_query($link, "INSERT INTO test_result VALUES (1, 'foo')");
+
+ mysqli_real_query($link, "SELECT * FROM test_result");
+ if (mysqli_field_count($link)) {
+ $result = mysqli_store_result($link);
+ $num = mysqli_num_fields($result);
+ mysqli_free_result($result);
+ }
+
+ var_dump($num);
+
+ mysqli_query($link, "DROP TABLE IF EXISTS test_result");
+ mysqli_close($link);
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS test_result"))
+ printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+mysqli_close($link);
+?>
+--EXPECT--
+int(2)
diff --git a/ext/mysqli/tests/039.phpt b/ext/mysqli/tests/039.phpt
new file mode 100644
index 0000000..ae881e1
--- /dev/null
+++ b/ext/mysqli/tests/039.phpt
@@ -0,0 +1,30 @@
+--TEST--
+function test: mysqli_num_fields() 2
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ /*** test mysqli_connect 127.0.0.1 ***/
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+ mysqli_real_query($link, "SHOW VARIABLES");
+
+ if (mysqli_field_count($link)) {
+ $result = mysqli_store_result($link);
+ $num = mysqli_num_fields($result);
+ mysqli_free_result($result);
+ }
+
+ var_dump($num);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--EXPECT--
+int(2)
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/040.phpt b/ext/mysqli/tests/040.phpt
new file mode 100644
index 0000000..3e28883
--- /dev/null
+++ b/ext/mysqli/tests/040.phpt
@@ -0,0 +1,47 @@
+--TEST--
+function test: mysqli_num_rows()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ /*** test mysqli_connect 127.0.0.1 ***/
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+ mysqli_select_db($link, $db);
+
+ mysqli_query($link, "DROP TABLE IF EXISTS test_result");
+ mysqli_query($link, "CREATE TABLE test_result (a int, b varchar(10)) ENGINE=" . $engine);
+ mysqli_query($link, "INSERT INTO test_result VALUES (1, 'foo')");
+
+ mysqli_real_query($link, "SELECT * FROM test_result");
+ if (mysqli_field_count($link)) {
+ $result = mysqli_store_result($link);
+ $num = mysqli_num_rows($result);
+ mysqli_free_result($result);
+ }
+
+ var_dump($num);
+
+ mysqli_query($link, "DROP TABLE IF EXISTS test_result");
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS test_result"))
+ printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+mysqli_close($link);
+?>
+--EXPECT--
+int(1)
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/041.phpt b/ext/mysqli/tests/041.phpt
new file mode 100644
index 0000000..ec67e47
--- /dev/null
+++ b/ext/mysqli/tests/041.phpt
@@ -0,0 +1,38 @@
+--TEST--
+function test: mysqli_warning_count()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+
+ require_once("connect.inc");
+
+ /*** test mysqli_connect 127.0.0.1 ***/
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+ mysqli_select_db($link, $db);
+
+ mysqli_query($link, "DROP TABLE IF EXISTS test_warnings");
+ mysqli_query($link, "DROP TABLE IF EXISTS test_warnings");
+
+ var_dump(mysqli_warning_count($link));
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS test_warnings"))
+ printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+mysqli_close($link);
+?>
+--EXPECT--
+int(1)
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/042.phpt b/ext/mysqli/tests/042.phpt
new file mode 100644
index 0000000..31f38f7
--- /dev/null
+++ b/ext/mysqli/tests/042.phpt
@@ -0,0 +1,79 @@
+--TEST--
+mysqli_fetch_object
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ /*** test mysqli_connect 127.0.0.1 ***/
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+ mysqli_select_db($link, $db);
+ mysqli_query($link, "SET sql_mode=''");
+
+ mysqli_query($link,"DROP TABLE IF EXISTS test_bind_fetch");
+ mysqli_query($link,"CREATE TABLE test_bind_fetch(c1 smallint unsigned,
+ c2 smallint unsigned,
+ c3 smallint,
+ c4 smallint,
+ c5 smallint,
+ c6 smallint unsigned,
+ c7 smallint) ENGINE=" . $engine);
+
+ $stmt = mysqli_prepare($link, "INSERT INTO test_bind_fetch VALUES (?,?,?,?,?,?,?)");
+ mysqli_stmt_bind_param($stmt, "iiiiiii", $c1,$c2,$c3,$c4,$c5,$c6,$c7);
+
+ $c1 = -23;
+ $c2 = 35999;
+ $c3 = NULL;
+ $c4 = -500;
+ $c5 = -9999999;
+ $c6 = -0;
+ $c7 = 0;
+
+ mysqli_stmt_execute($stmt);
+ mysqli_stmt_close($stmt);
+
+ $result = mysqli_query($link, "SELECT * FROM test_bind_fetch");
+ $test = mysqli_fetch_object($result);
+ mysqli_free_result($result);
+
+ var_dump($test);
+
+ mysqli_query($link, "DROP TABLE IF EXISTS test_bind_fetch");
+ mysqli_close($link);
+ print "done!"
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS test_bind_fetch"))
+ printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+mysqli_close($link);
+?>
+--EXPECTF--
+object(stdClass)#%d (7) {
+ [%u|b%"c1"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"c2"]=>
+ %unicode|string%(5) "35999"
+ [%u|b%"c3"]=>
+ NULL
+ [%u|b%"c4"]=>
+ %unicode|string%(4) "-500"
+ [%u|b%"c5"]=>
+ %unicode|string%(6) "-32768"
+ [%u|b%"c6"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"c7"]=>
+ %unicode|string%(1) "0"
+}
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/043.phpt b/ext/mysqli/tests/043.phpt
new file mode 100644
index 0000000..c3a9901
--- /dev/null
+++ b/ext/mysqli/tests/043.phpt
@@ -0,0 +1,59 @@
+--TEST--
+mysqli_stmt_bind_param (UPDATE)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ /*** test mysqli_connect 127.0.0.1 ***/
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+ mysqli_select_db($link, $db);
+
+ mysqli_query($link,"DROP TABLE IF EXISTS test_update");
+ mysqli_query($link,"CREATE TABLE test_update(a varchar(10),
+ b int) ENGINE=" . $engine);
+
+ mysqli_query($link, "INSERT INTO test_update VALUES ('foo', 2)");
+
+ $stmt = mysqli_prepare($link, "UPDATE test_update SET a=?,b=? WHERE b=?");
+ mysqli_stmt_bind_param($stmt, "sii", $c1, $c2, $c3);
+
+ $c1 = "Rasmus";
+ $c2 = 1;
+ $c3 = 2;
+
+ mysqli_stmt_execute($stmt);
+ mysqli_stmt_close($stmt);
+
+ $result = mysqli_query($link, "SELECT concat(a, ' is No. ', b) FROM test_update");
+ $test = mysqli_fetch_row($result);
+ mysqli_free_result($result);
+
+ var_dump($test);
+
+ mysqli_query($link, "DROP TABLE IF EXISTS test_update");
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS test_update"))
+ printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+mysqli_close($link);
+?>
+--EXPECTF--
+array(1) {
+ [0]=>
+ string(15) "Rasmus is No. 1"
+}
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/044.phpt b/ext/mysqli/tests/044.phpt
new file mode 100644
index 0000000..3ddae3e
--- /dev/null
+++ b/ext/mysqli/tests/044.phpt
@@ -0,0 +1,26 @@
+--TEST--
+mysqli_get_server_version
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ /*** test mysqli_connect 127.0.0.1 ***/
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+ $i = mysqli_get_server_version($link);
+
+ $test = $i / $i;
+
+ var_dump($test);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--EXPECT--
+int(1)
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/045.phpt b/ext/mysqli/tests/045.phpt
new file mode 100644
index 0000000..d11c166
--- /dev/null
+++ b/ext/mysqli/tests/045.phpt
@@ -0,0 +1,53 @@
+--TEST--
+mysqli_stmt_bind_result (SHOW)
+--SKIPIF--
+<?php
+ require_once('skipif.inc');
+ require_once('skipifemb.inc');
+ require_once('skipifconnectfailure.inc');
+
+ require_once("connect.inc");
+ $link = my_mysqli_connect($host, $user, $passwd);
+
+ $stmt = mysqli_prepare($link, "SHOW VARIABLES LIKE 'port'");
+ mysqli_stmt_execute($stmt);
+
+ if (!$stmt->field_count) {
+ printf("skip SHOW command is not supported in prepared statements.");
+ }
+ $stmt->close();
+ mysqli_close($link);
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ /*** test mysqli_connect 127.0.0.1 ***/
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+ $stmt = mysqli_prepare($link, "SHOW VARIABLES LIKE 'port'");
+ mysqli_stmt_execute($stmt);
+
+ mysqli_stmt_bind_result($stmt, $c1, $c2);
+ mysqli_stmt_fetch($stmt);
+ mysqli_stmt_close($stmt);
+ if ((version_compare(PHP_VERSION, '5.9.9', '>') == 1) && mysqli_get_server_version($link) < 50000) {
+ /* variables are binary */
+ settype($c1, "unicode");
+ settype($c2, "unicode");
+ }
+ $test = array ($c1,$c2);
+
+ var_dump($test);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--EXPECTF--
+array(2) {
+ [0]=>
+ %unicode|string%(4) "port"
+ [1]=>
+ %unicode|string%(%d) "%s"
+}
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/046.phpt b/ext/mysqli/tests/046.phpt
new file mode 100644
index 0000000..1abc5e7
--- /dev/null
+++ b/ext/mysqli/tests/046.phpt
@@ -0,0 +1,50 @@
+--TEST--
+mysqli_stmt_affected_rows (delete)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ /*** test mysqli_connect 127.0.0.1 ***/
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+ mysqli_select_db($link, $db);
+
+ mysqli_query($link, "DROP TABLE IF EXISTS test_affected");
+ mysqli_query($link, "CREATE TABLE test_affected (foo int) ENGINE=" . $engine);
+
+ mysqli_query($link, "INSERT INTO test_affected VALUES (1),(2),(3),(4),(5)");
+
+ $stmt = mysqli_prepare($link, "DELETE FROM test_affected WHERE foo=?");
+ mysqli_stmt_bind_param($stmt, "i", $c1);
+
+ $c1 = 2;
+
+ mysqli_stmt_execute($stmt);
+ $x = mysqli_stmt_affected_rows($stmt);
+
+ mysqli_stmt_close($stmt);
+ var_dump($x==1);
+
+ mysqli_query($link, "DROP TABLE IF EXISTS test_affected");
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS test_affected"))
+ printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+mysqli_close($link);
+?>
+--EXPECT--
+bool(true)
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/047.phpt b/ext/mysqli/tests/047.phpt
new file mode 100644
index 0000000..178a1ae
--- /dev/null
+++ b/ext/mysqli/tests/047.phpt
@@ -0,0 +1,237 @@
+--TEST--
+mysqli_stmt_result_metadata
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ /*** test mysqli_connect 127.0.0.1 ***/
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+ mysqli_select_db($link, $db);
+
+ mysqli_query($link, "DROP TABLE IF EXISTS test_affected");
+ mysqli_query($link, "CREATE TABLE test_affected (foo int, bar varchar(10) character set latin1) ENGINE=" . $engine);
+
+ mysqli_query($link, "INSERT INTO test_affected VALUES (1, 'Zak'),(2, 'Greant')");
+
+ $stmt = mysqli_prepare($link, "SELECT * FROM test_affected");
+ mysqli_stmt_execute($stmt);
+ $result = mysqli_stmt_result_metadata($stmt);
+
+ echo "\n=== fetch_fields ===\n";
+ var_dump(mysqli_fetch_fields($result));
+
+ echo "\n=== fetch_field_direct ===\n";
+ var_dump(mysqli_fetch_field_direct($result, 0));
+ var_dump(mysqli_fetch_field_direct($result, 1));
+
+ echo "\n=== fetch_field ===\n";
+ while ($field = mysqli_fetch_field($result)) {
+ var_dump($field);
+ }
+
+ print_r(mysqli_fetch_lengths($result));
+
+ mysqli_free_result($result);
+
+
+ mysqli_stmt_close($stmt);
+ mysqli_query($link, "DROP TABLE IF EXISTS test_affected");
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS test_affected"))
+ printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+mysqli_close($link);
+?>
+--EXPECTF--
+=== fetch_fields ===
+array(2) {
+ [0]=>
+ object(stdClass)#5 (13) {
+ [%u|b%"name"]=>
+ %unicode|string%(3) "foo"
+ [%u|b%"orgname"]=>
+ %unicode|string%(3) "foo"
+ [%u|b%"table"]=>
+ %unicode|string%(13) "test_affected"
+ [%u|b%"orgtable"]=>
+ %unicode|string%(13) "test_affected"
+ [%u|b%"def"]=>
+ %unicode|string%(0) ""
+ [%u|b%"db"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"catalog"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"max_length"]=>
+ int(0)
+ [%u|b%"length"]=>
+ int(%d)
+ [%u|b%"charsetnr"]=>
+ int(%d)
+ [%u|b%"flags"]=>
+ int(32768)
+ [%u|b%"type"]=>
+ int(3)
+ [%u|b%"decimals"]=>
+ int(0)
+ }
+ [1]=>
+ object(stdClass)#6 (13) {
+ [%u|b%"name"]=>
+ %unicode|string%(3) "bar"
+ [%u|b%"orgname"]=>
+ %unicode|string%(3) "bar"
+ [%u|b%"table"]=>
+ %unicode|string%(13) "test_affected"
+ [%u|b%"orgtable"]=>
+ %unicode|string%(13) "test_affected"
+ [%u|b%"def"]=>
+ %unicode|string%(0) ""
+ [%u|b%"db"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"catalog"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"max_length"]=>
+ int(0)
+ [%u|b%"length"]=>
+ int(%d)
+ [%u|b%"charsetnr"]=>
+ int(%d)
+ [%u|b%"flags"]=>
+ int(0)
+ [%u|b%"type"]=>
+ int(253)
+ [%u|b%"decimals"]=>
+ int(0)
+ }
+}
+
+=== fetch_field_direct ===
+object(stdClass)#6 (13) {
+ [%u|b%"name"]=>
+ %unicode|string%(3) "foo"
+ [%u|b%"orgname"]=>
+ %unicode|string%(3) "foo"
+ [%u|b%"table"]=>
+ %unicode|string%(13) "test_affected"
+ [%u|b%"orgtable"]=>
+ %unicode|string%(13) "test_affected"
+ [%u|b%"def"]=>
+ %unicode|string%(0) ""
+ [%u|b%"db"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"catalog"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"max_length"]=>
+ int(0)
+ [%u|b%"length"]=>
+ int(%d)
+ [%u|b%"charsetnr"]=>
+ int(%d)
+ [%u|b%"flags"]=>
+ int(32768)
+ [%u|b%"type"]=>
+ int(3)
+ [%u|b%"decimals"]=>
+ int(0)
+}
+object(stdClass)#6 (13) {
+ [%u|b%"name"]=>
+ %unicode|string%(3) "bar"
+ [%u|b%"orgname"]=>
+ %unicode|string%(3) "bar"
+ [%u|b%"table"]=>
+ %unicode|string%(13) "test_affected"
+ [%u|b%"orgtable"]=>
+ %unicode|string%(13) "test_affected"
+ [%u|b%"def"]=>
+ %unicode|string%(0) ""
+ [%u|b%"db"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"catalog"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"max_length"]=>
+ int(0)
+ [%u|b%"length"]=>
+ int(%d)
+ [%u|b%"charsetnr"]=>
+ int(%d)
+ [%u|b%"flags"]=>
+ int(0)
+ [%u|b%"type"]=>
+ int(253)
+ [%u|b%"decimals"]=>
+ int(0)
+}
+
+=== fetch_field ===
+object(stdClass)#6 (13) {
+ [%u|b%"name"]=>
+ %unicode|string%(3) "foo"
+ [%u|b%"orgname"]=>
+ %unicode|string%(3) "foo"
+ [%u|b%"table"]=>
+ %unicode|string%(13) "test_affected"
+ [%u|b%"orgtable"]=>
+ %unicode|string%(13) "test_affected"
+ [%u|b%"def"]=>
+ %unicode|string%(0) ""
+ [%u|b%"db"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"catalog"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"max_length"]=>
+ int(0)
+ [%u|b%"length"]=>
+ int(%d)
+ [%u|b%"charsetnr"]=>
+ int(%d)
+ [%u|b%"flags"]=>
+ int(32768)
+ [%u|b%"type"]=>
+ int(3)
+ [%u|b%"decimals"]=>
+ int(0)
+}
+object(stdClass)#5 (13) {
+ [%u|b%"name"]=>
+ %unicode|string%(3) "bar"
+ [%u|b%"orgname"]=>
+ %unicode|string%(3) "bar"
+ [%u|b%"table"]=>
+ %unicode|string%(13) "test_affected"
+ [%u|b%"orgtable"]=>
+ %unicode|string%(13) "test_affected"
+ [%u|b%"def"]=>
+ %unicode|string%(0) ""
+ [%u|b%"db"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"catalog"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"max_length"]=>
+ int(0)
+ [%u|b%"length"]=>
+ int(%d)
+ [%u|b%"charsetnr"]=>
+ int(%d)
+ [%u|b%"flags"]=>
+ int(0)
+ [%u|b%"type"]=>
+ int(253)
+ [%u|b%"decimals"]=>
+ int(0)
+}
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/048.phpt b/ext/mysqli/tests/048.phpt
new file mode 100644
index 0000000..afc0923
--- /dev/null
+++ b/ext/mysqli/tests/048.phpt
@@ -0,0 +1,79 @@
+--TEST--
+mysqli bind_result (OO-Style)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ /*** test mysqli_connect 127.0.0.1 ***/
+ $mysql = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+ $mysql->select_db($db);
+ $mysql->query("DROP TABLE IF EXISTS test_fetch_null");
+
+ $mysql->query("CREATE TABLE test_fetch_null(col1 tinyint, col2 smallint,
+ col3 int, col4 bigint,
+ col5 float, col6 double,
+ col7 date, col8 time,
+ col9 varbinary(10),
+ col10 varchar(50),
+ col11 char(20)) ENGINE=" . $engine);
+
+ $mysql->query("INSERT INTO test_fetch_null(col1,col10, col11) VALUES(1,'foo1', 1000),(2,'foo2', 88),(3,'foo3', 389789)");
+
+ $stmt = $mysql->prepare("SELECT col1, col2, col3, col4, col5, col6, col7, col8, col9, col10, col11 from test_fetch_null");
+ $stmt->bind_result($c1, $c2, $c3, $c4, $c5, $c6, $c7, $c8, $c9, $c10, $c11);
+ $stmt->execute();
+
+ $stmt->fetch();
+
+ $test = array($c1,$c2,$c3,$c4,$c5,$c6,$c7,$c8,$c9,$c10,$c11);
+
+ var_dump($test);
+
+ $stmt->close();
+ $mysql->query("DROP TABLE IF EXISTS test_fetch_null");
+ $mysql->close();
+ print "done!";
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS test_fetch_null"))
+ printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+mysqli_close($link);
+?>
+--EXPECTF--
+array(11) {
+ [0]=>
+ int(1)
+ [1]=>
+ NULL
+ [2]=>
+ NULL
+ [3]=>
+ NULL
+ [4]=>
+ NULL
+ [5]=>
+ NULL
+ [6]=>
+ NULL
+ [7]=>
+ NULL
+ [8]=>
+ NULL
+ [9]=>
+ %unicode|string%(4) "foo1"
+ [10]=>
+ %unicode|string%(4) "1000"
+}
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/049.phpt b/ext/mysqli/tests/049.phpt
new file mode 100644
index 0000000..c87f369
--- /dev/null
+++ b/ext/mysqli/tests/049.phpt
@@ -0,0 +1,33 @@
+--TEST--
+mysql_fetch_row (OO-Style)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ /*** test mysqli_connect 127.0.0.1 ***/
+ $mysql = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+ $mysql->select_db($db);
+ $result = $mysql->query("SELECT DATABASE()");
+ $row = $result->fetch_row();
+ $result->close();
+
+ var_dump($row);
+ if ($row[0] != $db)
+ printf("[001] Expecting '%s' got '%s'\n", $db, $row[0]);
+
+ $mysql->close();
+ print "done!";
+?>
+--EXPECTF--
+array(1) {
+ [0]=>
+ %unicode|string%(%d) "%s"
+}
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/050.phpt b/ext/mysqli/tests/050.phpt
new file mode 100644
index 0000000..448f164
--- /dev/null
+++ b/ext/mysqli/tests/050.phpt
@@ -0,0 +1,24 @@
+--TEST--
+non freed statement test
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ /************************
+ * non freed stamement
+ ************************/
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+ $stmt = mysqli_prepare($link, "SELECT CURRENT_USER()");
+ mysqli_stmt_execute($stmt);
+
+ mysqli_close($link);
+ printf("Ok\n");
+?>
+--EXPECT--
+Ok
diff --git a/ext/mysqli/tests/051.phpt b/ext/mysqli/tests/051.phpt
new file mode 100644
index 0000000..4a766fb
--- /dev/null
+++ b/ext/mysqli/tests/051.phpt
@@ -0,0 +1,25 @@
+--TEST--
+free statement after close
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ /************************
+ * free statement after close
+ ************************/
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+ $stmt1 = mysqli_prepare($link, "SELECT CURRENT_USER()");
+ mysqli_stmt_execute($stmt1);
+
+ mysqli_close($link);
+ @mysqli_stmt_close($stmt1);
+ printf("Ok\n");
+?>
+--EXPECT--
+Ok
diff --git a/ext/mysqli/tests/052.phpt b/ext/mysqli/tests/052.phpt
new file mode 100644
index 0000000..1d131f1
--- /dev/null
+++ b/ext/mysqli/tests/052.phpt
@@ -0,0 +1,25 @@
+--TEST--
+call statement after close
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ /************************
+ * statement call after close
+ ************************/
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+ $stmt2 = mysqli_prepare($link, "SELECT CURRENT_USER()");
+
+ mysqli_close($link);
+ @mysqli_stmt_execute($stmt2);
+ @mysqli_stmt_close($stmt2);
+ printf("Ok\n");
+?>
+--EXPECT--
+Ok
diff --git a/ext/mysqli/tests/053.phpt b/ext/mysqli/tests/053.phpt
new file mode 100644
index 0000000..a1840c9
--- /dev/null
+++ b/ext/mysqli/tests/053.phpt
@@ -0,0 +1,23 @@
+--TEST--
+not freed resultset
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ /************************
+ * non freed resultset
+ ************************/
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+ $result = mysqli_query($link, "SELECT CURRENT_USER()");
+ mysqli_close($link);
+ printf("Ok\n");
+
+?>
+--EXPECT--
+Ok
diff --git a/ext/mysqli/tests/054.phpt b/ext/mysqli/tests/054.phpt
new file mode 100644
index 0000000..6bd45a7
--- /dev/null
+++ b/ext/mysqli/tests/054.phpt
@@ -0,0 +1,23 @@
+--TEST--
+free resultset after close
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ /************************
+ * free resultset after close
+ ************************/
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+ $result1 = mysqli_query($link, "SELECT CURRENT_USER()");
+ mysqli_close($link);
+ mysqli_free_result($result1);
+ printf("Ok\n");
+?>
+--EXPECT--
+Ok
diff --git a/ext/mysqli/tests/055.phpt b/ext/mysqli/tests/055.phpt
new file mode 100644
index 0000000..c73266e
--- /dev/null
+++ b/ext/mysqli/tests/055.phpt
@@ -0,0 +1,22 @@
+--TEST--
+free nothing
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ /************************
+ * don't free anything
+ ************************/
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+ $result2 = mysqli_query($link, "SELECT CURRENT_USER()");
+ $stmt2 = mysqli_prepare($link, "SELECT CURRENT_USER()");
+ printf("Ok\n");
+?>
+--EXPECT--
+Ok
diff --git a/ext/mysqli/tests/056.phpt b/ext/mysqli/tests/056.phpt
new file mode 100644
index 0000000..413e678
--- /dev/null
+++ b/ext/mysqli/tests/056.phpt
@@ -0,0 +1,24 @@
+--TEST--
+extend mysqli
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ class foobar extends mysqli {
+ function test () {
+ return ("I do not like MySQL 4.1");
+ }
+ }
+
+ $foo = new foobar();
+ $foo->connect($host, $user, $passwd, $db, $port, $socket);
+ $foo->close();
+ printf("%s\n", $foo->test());
+?>
+--EXPECT--
+I do not like MySQL 4.1
diff --git a/ext/mysqli/tests/057.phpt b/ext/mysqli/tests/057.phpt
new file mode 100644
index 0000000..2cb8875
--- /dev/null
+++ b/ext/mysqli/tests/057.phpt
@@ -0,0 +1,113 @@
+--TEST--
+mysqli_stmt_result_metadata
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ /*** test mysqli_connect 127.0.0.1 ***/
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+ mysqli_select_db($link, $db);
+
+ mysqli_query($link,"DROP TABLE IF EXISTS test_store_result");
+ mysqli_query($link,"CREATE TABLE test_store_result (a int)");
+
+ mysqli_query($link, "INSERT INTO test_store_result VALUES (1),(2),(3)");
+
+ $stmt = mysqli_prepare($link, "SELECT * FROM test_store_result");
+ mysqli_stmt_execute($stmt);
+
+ /* this should produce an out of sync error */
+ if ($result = mysqli_query($link, "SELECT * FROM test_store_result")) {
+ mysqli_free_result($result);
+ printf ("Query ok\n");
+ }
+ mysqli_stmt_close($stmt);
+
+ /* now we should try mysqli_stmt_reset() */
+ $stmt = mysqli_prepare($link, "SELECT * FROM test_store_result");
+ var_dump(mysqli_stmt_execute($stmt));
+ var_dump(mysqli_stmt_reset($stmt));
+
+ var_dump($stmt = mysqli_prepare($link, "SELECT * FROM test_store_result"));
+ if ($IS_MYSQLND && $stmt->affected_rows !== -1)
+ printf("[001] Expecting -1, got %d\n", $stmt->affected_rows);
+
+ var_dump(mysqli_stmt_execute($stmt));
+ var_dump($stmt = @mysqli_prepare($link, "SELECT * FROM test_store_result"), mysqli_error($link));
+ var_dump(mysqli_stmt_reset($stmt));
+
+ $stmt = mysqli_prepare($link, "SELECT * FROM test_store_result");
+ mysqli_stmt_execute($stmt);
+ $result1 = mysqli_stmt_result_metadata($stmt);
+ mysqli_stmt_store_result($stmt);
+
+ printf ("Rows: %d\n", mysqli_stmt_affected_rows($stmt));
+
+ /* this should show an error, cause results are not buffered */
+ if ($result = mysqli_query($link, "SELECT * FROM test_store_result")) {
+ $row = mysqli_fetch_row($result);
+ mysqli_free_result($result);
+ }
+
+ var_dump($row);
+
+ mysqli_free_result($result1);
+ mysqli_stmt_close($stmt);
+ mysqli_close($link);
+ echo "done!";
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS test_store_result"))
+ printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+mysqli_close($link);
+?>
+--EXPECTF--
+bool(true)
+bool(true)
+object(mysqli_stmt)#%d (%d) {
+ [%u|b%"affected_rows"]=>
+ int(%i)
+ [%u|b%"insert_id"]=>
+ int(0)
+ [%u|b%"num_rows"]=>
+ int(0)
+ [%u|b%"param_count"]=>
+ int(0)
+ [%u|b%"field_count"]=>
+ int(1)
+ [%u|b%"errno"]=>
+ int(0)
+ [%u|b%"error"]=>
+ %unicode|string%(0) ""
+ [%u|b%"error_list"]=>
+ array(0) {
+ }
+ [%u|b%"sqlstate"]=>
+ %unicode|string%(5) "00000"
+ [%u|b%"id"]=>
+ int(3)
+}
+bool(true)
+bool(false)
+%unicode|string%(0) ""
+
+Warning: mysqli_stmt_reset() expects parameter 1 to be mysqli_stmt, boolean given in %s on line %d
+NULL
+Rows: 3
+array(1) {
+ [0]=>
+ %unicode|string%(1) "1"
+}
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/058.phpt b/ext/mysqli/tests/058.phpt
new file mode 100644
index 0000000..3d2eed7
--- /dev/null
+++ b/ext/mysqli/tests/058.phpt
@@ -0,0 +1,73 @@
+--TEST--
+multiple binds
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ /*** test mysqli_connect 127.0.0.1 ***/
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+ mysqli_select_db($link, $db);
+
+ mysqli_query($link,"DROP TABLE IF EXISTS mbind");
+ mysqli_query($link,"CREATE TABLE mbind (a int, b varchar(10))");
+
+ $stmt = mysqli_prepare($link, "INSERT INTO mbind VALUES (?,?)");
+
+ mysqli_stmt_bind_param($stmt, "is", $a, $b);
+
+ $a = 1;
+ $b = "foo";
+
+ mysqli_stmt_execute($stmt);
+
+ mysqli_stmt_bind_param($stmt, "is", $c, $d);
+
+ $c = 2;
+ $d = "bar";
+
+ mysqli_stmt_execute($stmt);
+ mysqli_stmt_close($stmt);
+
+ $stmt = mysqli_prepare($link, "SELECT * FROM mbind");
+ mysqli_stmt_execute($stmt);
+
+ mysqli_stmt_bind_result($stmt, $e, $f);
+ mysqli_stmt_fetch($stmt);
+
+ mysqli_stmt_bind_result($stmt, $g, $h);
+ mysqli_stmt_fetch($stmt);
+
+ var_dump((array($e,$f,$g,$h)));
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS mbind"))
+ printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+mysqli_close($link);
+?>
+--EXPECTF--
+array(4) {
+ [0]=>
+ int(1)
+ [1]=>
+ %unicode|string%(3) "foo"
+ [2]=>
+ int(2)
+ [3]=>
+ %unicode|string%(3) "bar"
+}
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/059.phpt b/ext/mysqli/tests/059.phpt
new file mode 100644
index 0000000..e4b6a0b
--- /dev/null
+++ b/ext/mysqli/tests/059.phpt
@@ -0,0 +1,57 @@
+--TEST--
+sqlmode + bind
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ /*** test mysqli_connect 127.0.0.1 ***/
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+ mysqli_select_db($link, $db);
+
+ mysqli_query($link, "SET SQL_MODE='PIPES_AS_CONCAT'");
+
+ mysqli_query($link,"DROP TABLE IF EXISTS mbind");
+ mysqli_query($link,"CREATE TABLE mbind (b varchar(25))");
+
+ $stmt = mysqli_prepare($link, "INSERT INTO mbind VALUES (?||?)");
+
+ mysqli_stmt_bind_param($stmt, "ss", $a, $b);
+
+ $a = "foo";
+ $b = "bar";
+
+ mysqli_stmt_execute($stmt);
+
+ mysqli_stmt_close($stmt);
+
+ $stmt = mysqli_prepare($link, "SELECT * FROM mbind");
+ mysqli_stmt_execute($stmt);
+
+ mysqli_stmt_bind_result($stmt, $e);
+ mysqli_stmt_fetch($stmt);
+
+ var_dump($e);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS mbind"))
+ printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+mysqli_close($link);
+?>
+--EXPECTF--
+%unicode|string%(6) "foobar"
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/060.phpt b/ext/mysqli/tests/060.phpt
new file mode 100644
index 0000000..5d17f8f
--- /dev/null
+++ b/ext/mysqli/tests/060.phpt
@@ -0,0 +1,74 @@
+--TEST--
+mysqli_fetch_object with classes
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ class test_class {
+ function __construct($arg1, $arg2) {
+ echo __METHOD__ . "($arg1,$arg2)\n";
+ }
+ }
+
+ /*** test mysqli_connect 127.0.0.1 ***/
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+ mysqli_select_db($link, $db);
+ mysqli_query($link, "SET sql_mode=''");
+
+ mysqli_query($link,"DROP TABLE IF EXISTS test_fetch");
+ mysqli_query($link,"CREATE TABLE test_fetch(c1 smallint unsigned,
+ c2 smallint unsigned,
+ c3 smallint,
+ c4 smallint,
+ c5 smallint,
+ c6 smallint unsigned,
+ c7 smallint)");
+
+ mysqli_query($link, "INSERT INTO test_fetch VALUES ( -23, 35999, NULL, -500, -9999999, -0, 0)");
+
+ $result = mysqli_query($link, "SELECT * FROM test_fetch");
+ $test = mysqli_fetch_object($result, 'test_class', array(1, 2));
+ mysqli_free_result($result);
+
+ var_dump($test);
+
+ mysqli_close($link);
+
+ echo "Done\n";
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS test_fetch"))
+ printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+mysqli_close($link);
+?>
+--EXPECTF--
+test_class::__construct(1,2)
+object(test_class)#%d (7) {
+ [%u|b%"c1"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"c2"]=>
+ %unicode|string%(5) "35999"
+ [%u|b%"c3"]=>
+ NULL
+ [%u|b%"c4"]=>
+ %unicode|string%(4) "-500"
+ [%u|b%"c5"]=>
+ %unicode|string%(6) "-32768"
+ [%u|b%"c6"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"c7"]=>
+ %unicode|string%(1) "0"
+}
+Done \ No newline at end of file
diff --git a/ext/mysqli/tests/061.phpt b/ext/mysqli/tests/061.phpt
new file mode 100644
index 0000000..5817d82
--- /dev/null
+++ b/ext/mysqli/tests/061.phpt
@@ -0,0 +1,78 @@
+--TEST--
+local infile handler
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+if (!function_exists('mysqli_set_local_infile_handler'))
+ die("skip - function not available.");
+
+$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+if (!$link)
+ die(sprintf("skip Can't connect [%d] %s", mysqli_connect_errno(), mysqli_connect_error()));
+
+include_once("local_infile_tools.inc");
+if ($msg = check_local_infile_support($link, $engine))
+ die(sprintf("skip %s, [%d] %s", $msg, $link->errno, $link->error));
+
+mysqli_close($link);
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ function my_read($fp, &$buffer, $buflen, &$error) {
+ $buffer = strrev(fread($fp, $buflen));
+ return(strlen($buffer));
+ }
+
+ /*** test mysqli_connect 127.0.0.1 ***/
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+ /* create temporary file */
+ $filename = dirname(__FILE__) . "061.csv";
+ $fp = fopen($filename, "w");
+ fwrite($fp, b"foo;bar");
+ fclose($fp);
+
+ if (!mysqli_query($link,"DROP TABLE IF EXISTS t_061"))
+ printf("Cannot drop table: [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ if (!mysqli_query($link,"CREATE TABLE t_061 (c1 varchar(10), c2 varchar(10))"))
+ printf("Cannot create table: [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, sprintf("LOAD DATA LOCAL INFILE '%s' INTO TABLE t_061 FIELDS TERMINATED BY ';'", mysqli_real_escape_string($link, $filename))))
+ printf("Cannot load data: [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ mysqli_set_local_infile_handler($link, "my_read");
+ if (!mysqli_query($link, sprintf("LOAD DATA LOCAL INFILE '%s' INTO TABLE t_061 FIELDS TERMINATED BY ';'", mysqli_real_escape_string($link, $filename))))
+ printf("Cannot load data using infile handler: [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if ($result = mysqli_query($link, "SELECT c1,c2 FROM t_061")) {
+ while (($row = mysqli_fetch_row($result))) {
+ printf("%s-%s\n", $row[0], $row[1]);
+ printf("%s-%s\n", gettype($row[0]), gettype($row[1]));
+ }
+ mysqli_free_result($result);
+ }
+
+ mysqli_close($link);
+ unlink($filename);
+ print "done!";
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS t_061"))
+ printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+mysqli_close($link);
+?>
+--EXPECTF--
+foo-bar
+%unicode|string%-%unicode|string%
+rab-oof
+%unicode|string%-%unicode|string%
+done!
diff --git a/ext/mysqli/tests/062.phpt b/ext/mysqli/tests/062.phpt
new file mode 100644
index 0000000..bc6198c
--- /dev/null
+++ b/ext/mysqli/tests/062.phpt
@@ -0,0 +1,30 @@
+--TEST--
+resultset constructor
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $mysql = new my_mysqli($host, $user, $passwd, $db, $port, $socket);
+
+ $mysql->real_query("SELECT 'foo' FROM DUAL");
+
+ $myresult = new mysqli_result($mysql);
+
+ $row = $myresult->fetch_row();
+ $myresult->close();
+ $mysql->close();
+
+ var_dump($row);
+ print "done!";
+?>
+--EXPECTF--
+array(1) {
+ [0]=>
+ %unicode|string%(3) "foo"
+}
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/063.phpt b/ext/mysqli/tests/063.phpt
new file mode 100644
index 0000000..b184d72
--- /dev/null
+++ b/ext/mysqli/tests/063.phpt
@@ -0,0 +1,24 @@
+--TEST--
+resultset constructor
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $mysql = new my_mysqli($host, $user, $passwd, $db, $port, $socket);
+
+ $stmt = new mysqli_stmt($mysql, "SELECT 'foo' FROM DUAL");
+ $stmt->execute();
+ $stmt->bind_result($foo);
+ $stmt->fetch();
+ $stmt->close();
+ $mysql->close();
+
+ var_dump($foo);
+?>
+--EXPECTF--
+%unicode|string%(3) "foo" \ No newline at end of file
diff --git a/ext/mysqli/tests/064.phpt b/ext/mysqli/tests/064.phpt
new file mode 100644
index 0000000..46af7a6
--- /dev/null
+++ b/ext/mysqli/tests/064.phpt
@@ -0,0 +1,24 @@
+--TEST--
+NULL binding
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $mysql = new my_mysqli($host, $user, $passwd, $db, $port, $socket);
+
+ $stmt = new mysqli_stmt($mysql, "SELECT NULL FROM DUAL");
+ $stmt->execute();
+ $stmt->bind_result($foo);
+ $stmt->fetch();
+ $stmt->close();
+ $mysql->close();
+
+ var_dump($foo);
+?>
+--EXPECT--
+NULL
diff --git a/ext/mysqli/tests/065.phpt b/ext/mysqli/tests/065.phpt
new file mode 100644
index 0000000..9426644
--- /dev/null
+++ b/ext/mysqli/tests/065.phpt
@@ -0,0 +1,55 @@
+--TEST--
+set character set
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+
+if (!function_exists('mysqli_set_charset')) {
+ die('skip mysqli_set_charset() not available');
+}
+if (version_compare(PHP_VERSION, '5.9.9', '>') == 1) {
+ die('skip set character set not functional with PHP 6 (fomerly PHP 6 && unicode.semantics=On)');
+}
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ if (!$mysql = new my_mysqli($host, $user, $passwd, $db, $port, $socket))
+ printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+ if (!mysqli_query($mysql, "SET sql_mode=''"))
+ printf("[002] Cannot set SQL-Mode, [%d] %s\n", mysqli_errno($mysql), mysqli_error($mysql));
+
+ $esc_str = chr(0xbf) . chr(0x5c);
+ $len = $charset = array();
+ $tmp = null;
+
+ if ($mysql->set_charset("latin1")) {
+ /* 5C should be escaped */
+ if (3 !== ($tmp = strlen($mysql->real_escape_string($esc_str))))
+ printf("[003] Expecting 3/int got %s/%s\n", gettype($tmp), $tmp);
+
+ if ('latin1' !== ($tmp = $mysql->character_set_name()))
+ printf("[004] Expecting latin1/string got %s/%s\n", gettype($tmp), $tmp);
+ }
+
+ if ($res = $mysql->query("SHOW CHARACTER SET LIKE 'gbk'")) {
+ $res->free_result();
+ if ($mysql->set_charset("gbk")) {
+ /* nothing should be escaped, it's a valid gbk character */
+
+ if (2 !== ($tmp = strlen($mysql->real_escape_string($esc_str))))
+ printf("[005] Expecting 2/int got %s/%s\n", gettype($tmp), $tmp);
+
+ if ('gbk' !== ($tmp = $mysql->character_set_name()))
+ printf("[005] Expecting gbk/string got %s/%s\n", gettype($tmp), $tmp);;
+ }
+ }
+ $mysql->close();
+
+ print "done!";
+?>
+--EXPECT--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/066.phpt b/ext/mysqli/tests/066.phpt
new file mode 100644
index 0000000..91dfce5
--- /dev/null
+++ b/ext/mysqli/tests/066.phpt
@@ -0,0 +1,43 @@
+--TEST--
+function test: mysqli_warning object
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ /*** test mysqli_connect 127.0.0.1 ***/
+ $mysql = new my_mysqli($host, $user, $passwd, $db, $port, $socket);
+
+ $mysql->query("DROP TABLE IF EXISTS test_warnings");
+
+ $mysql->query("CREATE TABLE test_warnings (a int not null) ENGINE=myisam");
+
+ $mysql->query("INSERT INTO test_warnings VALUES (1),(2),(NULL)");
+
+ if (($warning = $mysql->get_warnings())) {
+ do {
+ printf("Warning\n");
+ } while ($warning->next());
+ }
+
+ $mysql->close();
+ print "done!";
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS test_warnings"))
+ printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+mysqli_close($link);
+?>
+--EXPECT--
+Warning
+done!
diff --git a/ext/mysqli/tests/067.phpt b/ext/mysqli/tests/067.phpt
new file mode 100644
index 0000000..d5795bd
--- /dev/null
+++ b/ext/mysqli/tests/067.phpt
@@ -0,0 +1,81 @@
+--TEST--
+function test: nested selects (cursors)
+--SKIPIF--
+<?php
+ require_once('skipif.inc');
+ require_once('skipifconnectfailure.inc');
+ require_once("connect.inc");
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ die("skip Cannot connect to check required version");
+
+ /* skip cursor test for versions < 50004 */
+ if ((!$IS_MYSQLND && (mysqli_get_client_version() < 50009)) ||
+ (mysqli_get_server_version($link) < 50009)) {
+ die(sprintf("skip Client library doesn't support cursors (%s/%s)",
+ mysqli_get_client_version(), mysqli_get_server_version($link)));
+ }
+ mysqli_close($link);
+?>
+--FILE--
+<?php
+ function open_cursor($mysql, $query) {
+ if (!is_object($stmt = $mysql->prepare($query))) {
+ printf("[001] Cannot create statement object for '%s', [%d] %s\n",
+ $query, $mysql->errno, $mysql->error);
+ }
+
+ $stmt->attr_set(MYSQLI_STMT_ATTR_CURSOR_TYPE, MYSQLI_CURSOR_TYPE_READ_ONLY);
+ return $stmt;
+ }
+
+ require_once("connect.inc");
+ $mysql = new my_mysqli($host, $user, $passwd, $db, $port, $socket);
+
+ if ((!$IS_MYSQLND && mysqli_get_client_version() < 50009) ||
+ (mysqli_get_server_version($mysql) < 50009)) {
+ /* we really want to skip it... */
+ die(var_dump(63));
+ }
+
+ $a = array();
+
+ for ($i=0;$i < 3; $i++) {
+ $mysql->query("DROP TABLE IF EXISTS cursor$i");
+ $mysql->query("CREATE TABLE cursor$i (a int not null) ENGINE=" . $engine);
+ $mysql->query("INSERT INTO cursor$i VALUES (1),(2),(3),(4),(5),(6)");
+ $stmt[$i] = open_cursor($mysql, "SELECT a FROM cursor$i");
+ $stmt[$i]->execute();
+ $stmt[$i]->bind_result($a[$i]);
+ }
+
+
+ $cnt = 0;
+ while ($stmt[0]->fetch()) {
+ $stmt[1]->fetch();
+ $stmt[2]->fetch();
+ $cnt += $a[0] + $a[1] + $a[2];
+ }
+
+ for ($i=0; $i < 3; $i++) {
+ $stmt[$i]->close();
+ }
+
+ $mysql->close();
+ var_dump($cnt);
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+for ($i =0; $i < 3; $i++) {
+ if (!mysqli_query($link, sprintf("DROP TABLE IF EXISTS cursor%d", $i)))
+ printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+}
+
+mysqli_close($link);
+?>
+--EXPECT--
+int(63) \ No newline at end of file
diff --git a/ext/mysqli/tests/068.phpt b/ext/mysqli/tests/068.phpt
new file mode 100644
index 0000000..57a4a25
--- /dev/null
+++ b/ext/mysqli/tests/068.phpt
@@ -0,0 +1,11 @@
+--TEST--
+mysqli get_client_info
+--SKIPIF--
+<?php require_once('skipif.inc'); ?>
+--FILE--
+<?php
+ $s = mysqli_get_client_info();
+ echo gettype($s);
+?>
+--EXPECTF--
+%unicode|string% \ No newline at end of file
diff --git a/ext/mysqli/tests/069.phpt b/ext/mysqli/tests/069.phpt
new file mode 100644
index 0000000..ee76ca5
--- /dev/null
+++ b/ext/mysqli/tests/069.phpt
@@ -0,0 +1,38 @@
+--TEST--
+mysqli multi_query, next_result, more_results
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $mysql = new my_mysqli($host, $user, $passwd, $db, $port, $socket);
+ $mysql->multi_query('SELECT 1;SELECT 2');
+ do {
+ $res = $mysql->store_result();
+ if ($mysql->errno == 0) {
+ while ($arr = $res->fetch_assoc()) {
+ var_dump($arr);
+ }
+ $res->free();
+ }
+ if (!$mysql->more_results()) {
+ break;
+ }
+ } while (@$mysql->next_result());
+ $mysql->close();
+ print "done!";
+?>
+--EXPECTF--
+array(1) {
+ [1]=>
+ %unicode|string%(1) "1"
+}
+array(1) {
+ [2]=>
+ %unicode|string%(1) "2"
+}
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/070.phpt b/ext/mysqli/tests/070.phpt
new file mode 100644
index 0000000..b71d9b2
--- /dev/null
+++ b/ext/mysqli/tests/070.phpt
@@ -0,0 +1,19 @@
+--TEST--
+mysqli ping
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $mysql = new my_mysqli($host, $user, $passwd, $db, $port, $socket);
+ var_dump($mysql->ping());
+ $mysql->close();
+ print "done!";
+?>
+--EXPECT--
+bool(true)
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/071.phpt b/ext/mysqli/tests/071.phpt
new file mode 100644
index 0000000..6f45777
--- /dev/null
+++ b/ext/mysqli/tests/071.phpt
@@ -0,0 +1,74 @@
+--TEST--
+mysqli thread_id & kill
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $mysql = new my_mysqli($host, $user, $passwd, $db, $port, $socket);
+ $version = $mysql->server_version;
+
+ var_dump($mysql->ping());
+
+ $ret = $mysql->kill($mysql->thread_id);
+ if ($IS_MYSQLND) {
+ if ($ret !== true){
+ printf("[001] Expecting boolean/true got %s/%s\n", gettype($ret), var_export($ret, true));
+ }
+ } else {
+ /* libmysql return value seems to depend on server version */
+ if ((($version >= 50123) || ($version <= 40200)) && $version != 50200) {
+ /* TODO: find exact version */
+ if ($ret !== true){
+ printf("[001] Expecting boolean/true got %s/%s @\n", gettype($ret), var_export($ret, true), $version);
+ }
+ } else {
+ if ($ret !== false){
+ printf("[001] Expecting boolean/false got %s/%s @\n", gettype($ret), var_export($ret, true), $version);
+ }
+ }
+ }
+
+ var_dump($mysql->ping());
+
+ $mysql->close();
+
+ $mysql = new my_mysqli($host, $user, $passwd, $db, $port, $socket);
+
+ var_dump(mysqli_ping($mysql));
+
+ $ret = $mysql->kill($mysql->thread_id);
+ if ($IS_MYSQLND) {
+ if ($ret !== true){
+ printf("[002] Expecting boolean/true got %s/%s\n", gettype($ret), var_export($ret, true));
+ }
+ } else {
+ /* libmysql return value seems to depend on server version */
+ if ((($version >= 50123) || ($version <= 40200)) && $version != 50200) {
+ /* TODO: find exact version */
+ if ($ret !== true){
+ printf("[002] Expecting boolean/true got %s/%s @\n", gettype($ret), var_export($ret, true), $version);
+ }
+ } else {
+ if ($ret !== false){
+ printf("[002] Expecting boolean/false got %s/%s @\n", gettype($ret), var_export($ret, true), $version);
+ }
+ }
+ }
+
+ var_dump(mysqli_ping($mysql));
+
+ $mysql->close();
+ print "done!";
+?>
+--EXPECT--
+bool(true)
+bool(false)
+bool(true)
+bool(false)
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/072.phpt b/ext/mysqli/tests/072.phpt
new file mode 100644
index 0000000..a1e9983
--- /dev/null
+++ b/ext/mysqli/tests/072.phpt
@@ -0,0 +1,32 @@
+--TEST--
+mysqli warning_count, get_warnings
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $mysql = new my_mysqli($host, $user, $passwd, $db, $port, $socket);
+
+ $mysql->query("DROP TABLE IF EXISTS not_exists");
+
+ var_dump($mysql->warning_count);
+
+ $w = $mysql->get_warnings();
+
+ var_dump($w->errno);
+ var_dump($w->message);
+ var_dump($w->sqlstate);
+
+ $mysql->close();
+ echo "done!"
+?>
+--EXPECTF--
+int(1)
+int(1051)
+%unicode|string%(%d) "Unknown table %snot_exists%s"
+%unicode|string%(5) "HY000"
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/073.phpt b/ext/mysqli/tests/073.phpt
new file mode 100644
index 0000000..c70f7d9
--- /dev/null
+++ b/ext/mysqli/tests/073.phpt
@@ -0,0 +1,24 @@
+--TEST--
+mysqli_driver properties
+--SKIPIF--
+<?php require_once('skipif.inc'); ?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ var_dump($driver->embedded);
+ var_dump($driver->client_version);
+ var_dump($driver->client_info);
+ var_dump($driver->driver_version);
+ var_dump($driver->reconnect);
+ var_dump($driver->report_mode);
+ print "done!";
+?>
+--EXPECTF--
+bool(%s)
+int(%d)
+%unicode|string%(%d) "%s"
+int(%d)
+bool(%s)
+int(%d)
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/074.phpt b/ext/mysqli/tests/074.phpt
new file mode 100644
index 0000000..7d9d01b
--- /dev/null
+++ b/ext/mysqli/tests/074.phpt
@@ -0,0 +1,34 @@
+--TEST--
+mysqli_autocommit() tests
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+
+ require_once("connect.inc");
+
+ $mysqli = new my_mysqli($host, $user, $passwd, $db, $port, $socket);
+
+ var_dump($mysqli->autocommit(false));
+ $result = $mysqli->query("SELECT @@autocommit");
+ var_dump($result->fetch_row());
+
+ var_dump($mysqli->autocommit(true));
+ $result = $mysqli->query("SELECT @@autocommit");
+ var_dump($result->fetch_row());
+
+?>
+--EXPECTF--
+bool(true)
+array(1) {
+ [0]=>
+ %unicode|string%(1) "0"
+}
+bool(true)
+array(1) {
+ [0]=>
+ %unicode|string%(1) "1"
+} \ No newline at end of file
diff --git a/ext/mysqli/tests/bug28817.phpt b/ext/mysqli/tests/bug28817.phpt
new file mode 100644
index 0000000..254c0e5
--- /dev/null
+++ b/ext/mysqli/tests/bug28817.phpt
@@ -0,0 +1,42 @@
+--TEST--
+Bug #28817 (problems with properties declared in the class extending MySQLi)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ class my_mysql extends mysqli {
+ public $p_test;
+
+ function __construct() {
+ $this->p_test[] = "foo";
+ $this->p_test[] = "bar";
+ }
+ }
+
+
+ $mysql = new my_mysql();
+
+ var_dump($mysql->p_test);
+ @var_dump($mysql->errno);
+
+ $mysql->connect($host, $user, $passwd, $db, $port, $socket);
+ $mysql->select_db("nonexistingdb");
+
+ var_dump($mysql->errno > 0);
+
+ $mysql->close();
+?>
+--EXPECTF--
+array(2) {
+ [0]=>
+ %s(3) "foo"
+ [1]=>
+ %s(3) "bar"
+}
+NULL
+bool(true) \ No newline at end of file
diff --git a/ext/mysqli/tests/bug29311.phpt b/ext/mysqli/tests/bug29311.phpt
new file mode 100644
index 0000000..cd7b9ef
--- /dev/null
+++ b/ext/mysqli/tests/bug29311.phpt
@@ -0,0 +1,51 @@
+--TEST--
+Bug #29311 (Cannot override mysqli constructor)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ /* class 1 calls parent constructor */
+ class mysql1 extends mysqli {
+ function __construct() {
+ global $host, $user, $passwd, $db, $port, $socket;
+ parent::__construct($host, $user, $passwd, $db, $port, $socket);
+ }
+ }
+
+ /* class 2 has an own constructor */
+ class mysql2 extends mysqli {
+
+ function __construct() {
+ global $host, $user, $passwd, $db, $port, $socket;
+ $this->connect($host, $user, $passwd, $db, $port, $socket);
+ }
+ }
+
+ /* class 3 has no constructor */
+ class mysql3 extends mysqli {
+
+ }
+
+ $foo[0] = new mysql1();
+ $foo[1] = new mysql2();
+ $foo[2] = new mysql3($host, $user, $passwd, $db, $port, $socket);
+
+
+ for ($i=0; $i < 3; $i++) {
+ if (($result = $foo[$i]->query("SELECT DATABASE()"))) {
+ $row = $result->fetch_row();
+ if ($row[0] != $db)
+ printf("%d: %s\n", $i, $row[0]);
+ $result->close();
+ }
+ $foo[$i]->close();
+ }
+ print "done!";
+?>
+--EXPECTF--
+done!
diff --git a/ext/mysqli/tests/bug30967.phpt b/ext/mysqli/tests/bug30967.phpt
new file mode 100644
index 0000000..48007ce
--- /dev/null
+++ b/ext/mysqli/tests/bug30967.phpt
@@ -0,0 +1,26 @@
+--TEST--
+Bug #30967 (problems with properties declared in the class extending the class extending MySQLi)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ class mysql1 extends mysqli {
+ }
+
+ class mysql2 extends mysql1 {
+ }
+
+ $mysql = new mysql2($host, $user, $passwd, $db, $port, $socket);
+
+ $mysql->query("THIS DOES NOT WORK");
+ printf("%d\n", $mysql->errno);
+
+ $mysql->close();
+?>
+--EXPECTF--
+1064
diff --git a/ext/mysqli/tests/bug31141.phpt b/ext/mysqli/tests/bug31141.phpt
new file mode 100644
index 0000000..7183474
--- /dev/null
+++ b/ext/mysqli/tests/bug31141.phpt
@@ -0,0 +1,28 @@
+--TEST--
+Bug #31141 (properties declared in the class extending MySQLi are not available)
+--SKIPIF--
+<?php require_once('skipif.inc'); ?>
+--FILE--
+<?php
+class Test extends mysqli
+{
+ public $test = array();
+
+ function foo()
+ {
+ $ar_test = array("foo", "bar");
+ $this->test = &$ar_test;
+ }
+}
+
+$my_test = new Test;
+$my_test->foo();
+var_dump($my_test->test);
+?>
+--EXPECTF--
+array(2) {
+ [0]=>
+ %s(3) "foo"
+ [1]=>
+ %s(3) "bar"
+}
diff --git a/ext/mysqli/tests/bug31668.phpt b/ext/mysqli/tests/bug31668.phpt
new file mode 100644
index 0000000..9b769a1
--- /dev/null
+++ b/ext/mysqli/tests/bug31668.phpt
@@ -0,0 +1,61 @@
+--TEST--
+Bug #31668 (multi_query works exactly every other time (multi_query was global, now per connection))
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--INI--
+error_reporting = E_ALL & ~E_STRICT
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $mysql = new my_mysqli($host, $user, $passwd, $db, $port, $socket);
+ $mysql->multi_query('SELECT 1;SELECT 2');
+ do {
+ $res = $mysql->store_result();
+ if ($mysql->errno == 0) {
+ while ($arr = $res->fetch_assoc()) {
+ var_dump($arr);
+ }
+ $res->free();
+ }
+ } while ($mysql->next_result());
+ var_dump($mysql->error, __LINE__);
+ $mysql->close();
+
+ $mysql = new my_mysqli($host, $user, $passwd, $db, $port, $socket);
+ $mysql->multi_query('SELECT 1;SELECT 2');
+ do {
+ $res = $mysql->store_result();
+ if ($mysql->errno == 0) {
+ while ($arr = $res->fetch_assoc()) {
+ var_dump($arr);
+ }
+ $res->free();
+ }
+ } while ($mysql->next_result());
+ var_dump($mysql->error, __LINE__);
+?>
+--EXPECTF--
+array(1) {
+ [1]=>
+ %s(1) "1"
+}
+array(1) {
+ [2]=>
+ %s(1) "2"
+}
+%s(0) ""
+int(%d)
+array(1) {
+ [1]=>
+ %s(1) "1"
+}
+array(1) {
+ [2]=>
+ %s(1) "2"
+}
+%s(0) ""
+int(%d)
diff --git a/ext/mysqli/tests/bug32405.phpt b/ext/mysqli/tests/bug32405.phpt
new file mode 100644
index 0000000..0b3cad5
--- /dev/null
+++ b/ext/mysqli/tests/bug32405.phpt
@@ -0,0 +1,53 @@
+--TEST--
+Bug #32405 (mysqli->fetch() is returning bad data)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ /*** test mysqli_connect 127.0.0.1 ***/
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+ mysqli_select_db($link, "test");
+ mysqli_query($link, "SET sql_mode=''");
+
+ /* two fields are needed. the problem does not occur with 1 field only selected. */
+ $link->query("CREATE TABLE test_users(user_id int(10) unsigned NOT NULL auto_increment, login varchar(50) default '', PRIMARY KEY (user_id))");
+ $link->query('INSERT INTO test_users VALUES (NULL, "user1"), (NULL, "user2"), (NULL, "user3"), (NULL, "user4")');
+
+
+ if ($stmt = $link->prepare("SELECT SQL_NO_CACHE user_id, login FROM test_users")) {
+ $stmt->execute();
+ $stmt->bind_result($col1, $col2);
+ while ($stmt->fetch()) {
+ var_dump($col1, $col2);
+ }
+ $stmt->close();
+ }
+
+ mysqli_query($link,"DROP TABLE test_users");
+ mysqli_close($link);
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS test_users"))
+ printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+mysqli_close($link);
+?>
+--EXPECTF--
+int(1)
+%s(5) "user1"
+int(2)
+%s(5) "user2"
+int(3)
+%s(5) "user3"
+int(4)
+%s(5) "user4"
diff --git a/ext/mysqli/tests/bug33090.phpt b/ext/mysqli/tests/bug33090.phpt
new file mode 100644
index 0000000..c95043c
--- /dev/null
+++ b/ext/mysqli/tests/bug33090.phpt
@@ -0,0 +1,24 @@
+--TEST--
+Bug #33090 (mysql_prepare doesn't return an error)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ include ("connect.inc");
+
+ /*** test mysqli_connect 127.0.0.1 ***/
+ $link = my_mysqli_connect($host, $user, $passwd, null, $port, $socket);
+ mysqli_select_db($link, $db);
+
+ if (!($link->prepare("this makes no sense"))) {
+ printf("%d\n", $link->errno);
+ printf("%s\n", $link->sqlstate);
+ }
+ $link->close();
+?>
+--EXPECT--
+1064
+42000
diff --git a/ext/mysqli/tests/bug33263.phpt b/ext/mysqli/tests/bug33263.phpt
new file mode 100644
index 0000000..ac2de19
--- /dev/null
+++ b/ext/mysqli/tests/bug33263.phpt
@@ -0,0 +1,37 @@
+--TEST--
+Bug #33263 (mysqli_real_connect in __construct)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ class test extends mysqli
+ {
+ public function __construct($host, $user, $passwd, $db, $port, $socket) {
+ parent::init();
+ parent::real_connect($host, $user, $passwd, $db, $port, $socket);
+ }
+ }
+
+ $mysql = new test($host, $user, $passwd, $db, $port, $socket);
+
+ $stmt = $mysql->prepare("SELECT DATABASE()");
+ $stmt->execute();
+ $stmt->bind_result($database);
+ $stmt->fetch();
+ $stmt->close();
+
+ if ($database != $db)
+ printf("[001] Expecting '%s' got %s/'%s'.\n",
+ gettype($database), $database);
+
+ $mysql->close();
+ print "done!";
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/bug33491.phpt b/ext/mysqli/tests/bug33491.phpt
new file mode 100644
index 0000000..168ecb0
--- /dev/null
+++ b/ext/mysqli/tests/bug33491.phpt
@@ -0,0 +1,29 @@
+--TEST--
+Bug #33491 (extended mysqli class crashes when result is not object)
+--INI--
+error_reporting=4095
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+
+class DB extends mysqli
+{
+ public function query_single($query) {
+ $result = parent::query($query);
+ $result->fetch_row(); // <- Here be crash
+ }
+}
+
+require_once("connect.inc");
+
+// Segfault when using the DB class which extends mysqli
+$DB = new DB($host, $user, $passwd, $db, $port, $socket);
+$DB->query_single('SELECT DATE()');
+
+?>
+--EXPECTF--
+Fatal error: Call to a member function fetch_row() on a non-object in %sbug33491.php on line %d
diff --git a/ext/mysqli/tests/bug34785.phpt b/ext/mysqli/tests/bug34785.phpt
new file mode 100644
index 0000000..18dd4c3
--- /dev/null
+++ b/ext/mysqli/tests/bug34785.phpt
@@ -0,0 +1,50 @@
+--TEST--
+Bug #34785 (Can not properly subclass mysqli_stmt)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ include ("connect.inc");
+
+ class my_stmt extends mysqli_stmt
+ {
+ public function __construct($link, $query) {
+ parent::__construct($link, $query);
+ }
+ }
+
+ class my_result extends mysqli_result
+ {
+ public function __construct($link, $query) {
+ parent::__construct($link, $query);
+ }
+ }
+
+ /*** test mysqli_connect 127.0.0.1 ***/
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+ mysqli_query($link, "SET sql_mode=''");
+
+ $stmt = new my_stmt($link, "SELECT 'foo' FROM DUAL");
+
+ $stmt->execute();
+ $stmt->bind_result($var);
+ $stmt->fetch();
+
+ $stmt->close();
+ var_dump($var);
+
+ mysqli_real_query($link, "SELECT 'bar' FROM DUAL");
+ $result = new my_result($link, MYSQLI_STORE_RESULT);
+ $row = $result->fetch_row();
+ $result->close();
+
+ var_dump($row[0]);
+
+ mysqli_close($link);
+?>
+--EXPECTF--
+%s(3) "foo"
+%s(3) "bar"
diff --git a/ext/mysqli/tests/bug34810.phpt b/ext/mysqli/tests/bug34810.phpt
new file mode 100644
index 0000000..1ea89d9
--- /dev/null
+++ b/ext/mysqli/tests/bug34810.phpt
@@ -0,0 +1,146 @@
+--TEST--
+Bug #34810 (mysqli::init() and others use wrong $this pointer without checks)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+
+class DbConnection {
+ public function connect() {
+ require_once("connect.inc");
+
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+ var_dump($link);
+
+ $link = mysqli_init();
+ /* @ is to supress 'Property access is not allowed yet' */
+ @var_dump($link);
+
+ $mysql = new my_mysqli($host, $user, $passwd, $db, $port, $socket);
+ $mysql->query("DROP TABLE IF EXISTS test_warnings");
+ $mysql->query("CREATE TABLE test_warnings (a int not null)");
+ $mysql->query("SET sql_mode=''");
+ $mysql->query("INSERT INTO test_warnings VALUES (1),(2),(NULL)");
+
+ $warning = $mysql->get_warnings();
+ if (!$warning)
+ printf("[001] No warning!\n");
+
+ if ($warning->errno == 1048 || $warning->errno == 1253) {
+ /* 1048 - Column 'a' cannot be null, 1263 - Data truncated; NULL supplied to NOT NULL column 'a' at row */
+ if ("HY000" != $warning->sqlstate)
+ printf("[003] Wrong sql state code: %s\n", $warning->sqlstate);
+
+ if ("" == $warning->message)
+ printf("[004] Message string must not be empty\n");
+
+
+ } else {
+ printf("[002] Empty error message!\n");
+ var_dump($warning);
+ }
+ }
+}
+
+$db = new DbConnection();
+$db->connect();
+
+echo "Done\n";
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS test_warnings"))
+ printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+mysqli_close($link);
+?>
+--EXPECTF--
+object(mysqli)#%d (%d) {
+ [%u|b%"affected_rows"]=>
+ int(0)
+ [%u|b%"client_info"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"client_version"]=>
+ int(%d)
+ [%u|b%"connect_errno"]=>
+ int(0)
+ [%u|b%"connect_error"]=>
+ NULL
+ [%u|b%"errno"]=>
+ int(0)
+ [%u|b%"error"]=>
+ %unicode|string%(0) ""
+ [%u|b%"error_list"]=>
+ array(0) {
+ }
+ [%u|b%"field_count"]=>
+ int(0)
+ [%u|b%"host_info"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"info"]=>
+ NULL
+ [%u|b%"insert_id"]=>
+ int(0)
+ [%u|b%"server_info"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"server_version"]=>
+ int(%d)
+ [%u|b%"stat"]=>
+ string(%d) "Uptime: %d Threads: %d Questions: %d Slow queries: %d Opens: %d Flush tables: %d Open tables: %d Queries per second avg: %d.%d"
+ [%u|b%"sqlstate"]=>
+ %unicode|string%(5) "00000"
+ [%u|b%"protocol_version"]=>
+ int(10)
+ [%u|b%"thread_id"]=>
+ int(%d)
+ [%u|b%"warning_count"]=>
+ int(0)
+}
+object(mysqli)#%d (%d) {
+ [%u|b%"affected_rows"]=>
+ NULL
+ [%u|b%"client_info"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"client_version"]=>
+ int(%d)
+ [%u|b%"connect_errno"]=>
+ int(0)
+ [%u|b%"connect_error"]=>
+ NULL
+ [%u|b%"errno"]=>
+ int(0)
+ [%u|b%"error"]=>
+ %unicode|string%(0) ""
+ [%u|b%"error_list"]=>
+ NULL
+ [%u|b%"field_count"]=>
+ NULL
+ [%u|b%"host_info"]=>
+ NULL
+ [%u|b%"info"]=>
+ NULL
+ [%u|b%"insert_id"]=>
+ NULL
+ [%u|b%"server_info"]=>
+ NULL
+ [%u|b%"server_version"]=>
+ NULL
+ [%u|b%"stat"]=>
+ NULL
+ [%u|b%"sqlstate"]=>
+ NULL
+ [%u|b%"protocol_version"]=>
+ NULL
+ [%u|b%"thread_id"]=>
+ NULL
+ [%u|b%"warning_count"]=>
+ NULL
+}
+Done
diff --git a/ext/mysqli/tests/bug35103.phpt b/ext/mysqli/tests/bug35103.phpt
new file mode 100644
index 0000000..fc3cad0
--- /dev/null
+++ b/ext/mysqli/tests/bug35103.phpt
@@ -0,0 +1,82 @@
+--TEST--
+Bug #35103 (Bad handling of unsigned bigint)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+
+$drop = <<<EOSQL
+DROP TABLE test_bint;
+DROP TABLE test_buint;
+EOSQL;
+ require_once("connect.inc");
+
+ $mysql = new my_mysqli($host, $user, $passwd, $db, $port, $socket);
+ $mysql->query("DROP TABLE IF EXISTS test_bint");
+ $mysql->query("CREATE TABLE test_bint (a bigint(20) default NULL) ENGINE=MYISAM");
+ $mysql->query("INSERT INTO test_bint VALUES (9223372036854775807),(-9223372036854775808),(-2147483648),(-2147483649),(-2147483647),(2147483647),(2147483648),(2147483649)");
+
+ $mysql->query("DROP TABLE IF EXISTS test_buint");
+ $mysql->query("CREATE TABLE test_buint (a bigint(20) unsigned default NULL)");
+ $mysql->query("INSERT INTO test_buint VALUES (18446744073709551615),(9223372036854775807),(9223372036854775808),(2147483647),(2147483649),(4294967295)");
+
+ $stmt = $mysql->prepare("SELECT a FROM test_bint ORDER BY a");
+ $stmt->bind_result($v);
+ $stmt->execute();
+ $i=0;
+ echo "BIG INT SIGNED, TEST\n";
+ while ($i++ < 8) {
+ $stmt->fetch();
+ echo $v, "\n";
+ }
+ $stmt->close();
+
+ echo str_repeat("-", 20), "\n";
+
+ $stmt = $mysql->prepare("SELECT a FROM test_buint ORDER BY a");
+ $stmt->bind_result($v2);
+ $stmt->execute();
+ $j=0;
+ echo "BIG INT UNSIGNED TEST\n";
+ while ($j++ < 6) {
+ $stmt->fetch();
+ echo $v2, "\n";
+ }
+ $stmt->close();
+
+ $mysql->multi_query($drop);
+
+ $mysql->close();
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS test_bint") || !mysqli_query($link, "DROP TABLE IF EXISTS test_buint"))
+ printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+mysqli_close($link);
+?>
+--EXPECT--
+BIG INT SIGNED, TEST
+-9223372036854775808
+-2147483649
+-2147483648
+-2147483647
+2147483647
+2147483648
+2147483649
+9223372036854775807
+--------------------
+BIG INT UNSIGNED TEST
+2147483647
+2147483649
+4294967295
+9223372036854775807
+9223372036854775808
+18446744073709551615
diff --git a/ext/mysqli/tests/bug35517.phpt b/ext/mysqli/tests/bug35517.phpt
new file mode 100644
index 0000000..746251f
--- /dev/null
+++ b/ext/mysqli/tests/bug35517.phpt
@@ -0,0 +1,56 @@
+--TEST--
+Bug #35517 (mysqli_stmt_fetch returns NULL)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $mysql = new my_mysqli($host, $user, $passwd, $db, $port, $socket);
+
+ $mysql->query("CREATE TABLE temp (id INT UNSIGNED NOT NULL)");
+ $mysql->query("INSERT INTO temp (id) VALUES (3000000897),(3800001532),(3900002281),(3100059612)");
+ $stmt = $mysql->prepare("SELECT id FROM temp");
+ $stmt->execute();
+ $stmt->bind_result($id);
+ while ($stmt->fetch()) {
+ if (PHP_INT_SIZE == 8) {
+ if ((gettype($id) !== 'int') && (gettype($id) != 'integer'))
+ printf("[001] Expecting integer on 64bit got %s/%s\n", gettype($id), var_export($id, true));
+ } else {
+ if (gettype($id) !== 'string') {
+ printf("[002] Expecting string on 32bit got %s/%s\n", gettype($id), var_export($id, true));
+ }
+ if ((version_compare(PHP_VERSION, '5.9.9', '>') == 1) && !is_unicode($id)) {
+ printf("[003] Expecting unicode string\n");
+ }
+ }
+ print $id;
+ print "\n";
+ }
+ $stmt->close();
+
+ $mysql->query("DROP TABLE temp");
+ $mysql->close();
+ print "done!";
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS temp"))
+ printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+mysqli_close($link);
+?>
+--EXPECTF--
+3000000897
+3800001532
+3900002281
+3100059612
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/bug35759.phpt b/ext/mysqli/tests/bug35759.phpt
new file mode 100644
index 0000000..99c1380
--- /dev/null
+++ b/ext/mysqli/tests/bug35759.phpt
@@ -0,0 +1,58 @@
+--TEST--
+Bug #35759 (mysqli_stmt_bind_result() makes huge allocation when column empty)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+
+ require_once("connect.inc");
+ $col_num= 1000;
+
+ $mysql = new mysqli($host, $user, $passwd, $db, $port, $socket);
+ $mysql->query("DROP TABLE IF EXISTS test");
+ $create = "CREATE TABLE test (a0 MEDIUMBLOB NOT NULL DEFAULT ''";
+ $i= 0;
+ while (++$i < $col_num) {
+ $create .= ", a$i MEDIUMBLOB NOT NULL DEFAULT ''";
+ }
+ $create .= ") ENGINE=MyISAM"; // doesn't work with InnoDB, which is default in 5.5
+
+ if (!$mysql->query($create)) {
+ if (1101 == $mysql->errno) {
+ /* SQL strict mode - [1101] BLOB/TEXT column 'a0' can't have a default value */
+ print "done!";
+ exit(0);
+ }
+ printf("[001] [%d] %s\n", $mysql->errno, $mysql->error);
+ }
+
+ if (!$mysql->query("INSERT INTO test (a0) VALUES ('')"))
+ printf("[002] [%d] %s\n", $mysql->errno, $mysql->error);
+
+ $stmt = $mysql->prepare("SELECT * FROM test");
+ if ($stmt) {
+
+ $stmt->execute();
+ $stmt->store_result();
+ for ($i = 0; $i < $col_num; $i++) {
+ $params[] = &$col_num;
+ }
+ call_user_func_array(array($stmt, "bind_result"), $params);
+ $stmt->fetch();
+
+ $stmt->close();
+ } else {
+ printf("[003] [%d] %s\n", $mysql->errno, $mysql->error);
+ }
+
+ $mysql->close();
+
+ echo "done!";
+?>
+--CLEAN--
+<?php require("clean_table.inc"); ?>
+--EXPECT--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/bug36420.phpt b/ext/mysqli/tests/bug36420.phpt
new file mode 100644
index 0000000..6dd03b3
--- /dev/null
+++ b/ext/mysqli/tests/bug36420.phpt
@@ -0,0 +1,28 @@
+--TEST--
+Bug #36420 (segfault when access result->num_rows after calling result->close())
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+
+require_once("connect.inc");
+$mysqli = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+$result = $mysqli->query('select 1');
+
+$result->close();
+echo $result->num_rows;
+
+$mysqli->close();
+echo $result->num_rows;
+
+echo "Done\n";
+?>
+--EXPECTF--
+Warning: main(): Couldn't fetch mysqli_result in %s on line %d
+
+Warning: main(): Couldn't fetch mysqli_result in %s on line %d
+Done
diff --git a/ext/mysqli/tests/bug36745.phpt b/ext/mysqli/tests/bug36745.phpt
new file mode 100644
index 0000000..5e203e1
--- /dev/null
+++ b/ext/mysqli/tests/bug36745.phpt
@@ -0,0 +1,37 @@
+--TEST--
+Bug #36745 (LOAD DATA LOCAL INFILE doesn't return correct error message)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ /*** test mysqli_connect 127.0.0.1 ***/
+ $mysql = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+ $mysql->query("DROP TABLE IF EXISTS litest");
+ $mysql->query("CREATE TABLE litest (a VARCHAR(20))");
+
+ $mysql->query("LOAD DATA LOCAL INFILE 'filenotfound' INTO TABLE litest");
+ var_dump($mysql->error);
+
+ $mysql->close();
+ printf("Done");
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS litest"))
+ printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+mysqli_close($link);
+?>
+--EXPECTF--
+%s(%d) "%s"
+Done
diff --git a/ext/mysqli/tests/bug36802.phpt b/ext/mysqli/tests/bug36802.phpt
new file mode 100644
index 0000000..3694a26
--- /dev/null
+++ b/ext/mysqli/tests/bug36802.phpt
@@ -0,0 +1,41 @@
+--TEST--
+Bug #36802 (crashes with with mysqli_set_charset())
+--SKIPIF--
+<?php require_once('skipif.inc'); ?>
+--FILE--
+<?php
+ class really_my_mysqli extends mysqli {
+ function __construct()
+ {
+ }
+ }
+
+ require_once("connect.inc");
+ $mysql = mysqli_init();
+
+ /* following operations should not work */
+ if (method_exists($mysql, 'set_charset')) {
+ $x[0] = @$mysql->set_charset('utf8');
+ } else {
+ $x[0] = NULL;
+ }
+ $x[1] = @$mysql->query("SELECT 'foo' FROM DUAL");
+
+ /* following operations should work */
+ $x[2] = ($mysql->client_version > 0);
+ $x[3] = $mysql->errno;
+ $mysql->close();
+
+ var_dump($x);
+?>
+--EXPECT--
+array(4) {
+ [0]=>
+ NULL
+ [1]=>
+ NULL
+ [2]=>
+ bool(true)
+ [3]=>
+ int(0)
+}
diff --git a/ext/mysqli/tests/bug36949.phpt b/ext/mysqli/tests/bug36949.phpt
new file mode 100644
index 0000000..2b3cc49
--- /dev/null
+++ b/ext/mysqli/tests/bug36949.phpt
@@ -0,0 +1,63 @@
+--TEST--
+Bug #36949 (invalid internal mysqli objects dtor)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+require_once("connect.inc");
+class A {
+
+ private $mysqli;
+
+ public function __construct() {
+ global $user, $host, $passwd, $db, $port, $socket;
+ $this->mysqli = new mysqli($host, $user, $passwd, $db, $port, $socket);
+ $result = $this->mysqli->query("SELECT NOW() AS my_time FROM DUAL");
+ $row = $result->fetch_object();
+ echo $row->my_time."<br>\n";
+ $result->close();
+ }
+
+ public function __destruct() {
+ $this->mysqli->close();
+ }
+}
+
+class B {
+
+ private $mysqli;
+
+ public function __construct() {
+ global $user, $host, $passwd, $db, $port, $socket;
+ $this->mysqli = new mysqli($host, $user, $passwd, $db, $port, $socket);
+ $result = $this->mysqli->query("SELECT NOW() AS my_time FROM DUAL");
+ $row = $result->fetch_object();
+ echo $row->my_time."<br>\n";
+ $result->close();
+ }
+
+ public function __destruct() {
+ $this->mysqli->close();
+ }
+}
+
+$A = new A();
+$B = new B();
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS my_time"))
+ printf("[002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+mysqli_close($link);
+?>
+--EXPECTF--
+%d%d%d%d-%d%d-%d%d %d%d:%d%d:%d%d<br>
+%d%d%d%d-%d%d-%d%d %d%d:%d%d:%d%d<br>
diff --git a/ext/mysqli/tests/bug37090.phpt b/ext/mysqli/tests/bug37090.phpt
new file mode 100644
index 0000000..839081d
--- /dev/null
+++ b/ext/mysqli/tests/bug37090.phpt
@@ -0,0 +1,48 @@
+--TEST--
+Bug #37090 (mysqli_set_charset return code)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+if (!function_exists('mysqli_set_charset')) {
+ die('skip mysqli_set_charset() not available');
+}
+if ((version_compare(PHP_VERSION, '5.9.9', '>') == 1)) {
+ die("skip Functionality not available in unicode mode");
+}
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $mysql = new my_mysqli($host, $user, $passwd, $db, $port, $socket);
+
+ $cs = array();
+ $cs[] = $mysql->set_charset("latin1");
+ $cs[] = $mysql->character_set_name();
+
+ $cs[] = $mysql->set_charset("utf8");
+ $cs[] = $mysql->character_set_name();
+
+ $cs[] = $mysql->set_charset("notdefined");
+ $cs[] = $mysql->character_set_name();
+
+ var_dump($cs);
+ print "done!";
+?>
+--EXPECT--
+array(6) {
+ [0]=>
+ bool(true)
+ [1]=>
+ string(6) "latin1"
+ [2]=>
+ bool(true)
+ [3]=>
+ string(4) "utf8"
+ [4]=>
+ bool(false)
+ [5]=>
+ string(4) "utf8"
+}
+done!
diff --git a/ext/mysqli/tests/bug38003.phpt b/ext/mysqli/tests/bug38003.phpt
new file mode 100644
index 0000000..af71f85
--- /dev/null
+++ b/ext/mysqli/tests/bug38003.phpt
@@ -0,0 +1,20 @@
+--TEST--
+Bug #38003 (in classes inherited from MySQLi it's possible to call private constructors from invalid context)
+--SKIPIF--
+<?php if (!extension_loaded("mysqli")) print "skip"; ?>
+--FILE--
+<?php
+
+class DB extends mysqli {
+
+ private function __construct($hostname, $username, $password, $database) {
+ var_dump("DB::__construct() called");
+ }
+}
+
+$DB = new DB();
+
+echo "Done\n";
+?>
+--EXPECTF--
+Fatal error: Call to private DB::__construct() from invalid context in %s on line %d
diff --git a/ext/mysqli/tests/bug38710.phpt b/ext/mysqli/tests/bug38710.phpt
new file mode 100644
index 0000000..c3bb728
--- /dev/null
+++ b/ext/mysqli/tests/bug38710.phpt
@@ -0,0 +1,24 @@
+--TEST--
+Bug #38710 (data leakage because of nonexisting boundary checking in statements)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+require_once("connect.inc");
+
+$db = new my_mysqli($host, $user, $passwd, $db, $port, $socket);
+$qry=$db->stmt_init();
+$qry->prepare("SELECT REPEAT('a',100000)");
+$qry->execute();
+$qry->bind_result($text);
+$qry->fetch();
+if ($text !== str_repeat('a', ($IS_MYSQLND || mysqli_get_server_version($db) > 50110)? 100000:(mysqli_get_server_version($db)>=50000? 8193:8191))) {
+ var_dump(strlen($text));
+}
+echo "Done";
+?>
+--EXPECTF--
+Done \ No newline at end of file
diff --git a/ext/mysqli/tests/bug39457.phpt b/ext/mysqli/tests/bug39457.phpt
new file mode 100644
index 0000000..ec9239b
--- /dev/null
+++ b/ext/mysqli/tests/bug39457.phpt
@@ -0,0 +1,21 @@
+--TEST--
+Bug #39457 (Multiple invoked OO connections never close)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $mysql = mysqli_init();
+ $mysql->connect($host, $user, $passwd, $db, $port, $socket);
+
+ $mysql->connect($host, $user, $passwd, $db, $port, $socket);
+
+ $mysql->close();
+ echo "OK\n";
+?>
+--EXPECT--
+OK
diff --git a/ext/mysqli/tests/bug42378.phpt b/ext/mysqli/tests/bug42378.phpt
new file mode 100644
index 0000000..b3fd7ca
--- /dev/null
+++ b/ext/mysqli/tests/bug42378.phpt
@@ -0,0 +1,197 @@
+--TEST--
+Bug #42378 (bind_result memory exhaustion, SELECT column, FORMAT(...) AS _format)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--INI--
+memory_limit=83886080
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ function create_table($link, $column, $min, $max, $engine, $offset) {
+
+ if (!mysqli_query($link, 'DROP TABLE IF EXISTS test')) {
+ printf("[%03d] Cannot drop table test, [%d] %s\n",
+ $offset,
+ mysqli_errno($link), mysqli_error($link));
+ return array();
+ }
+ print "$column\n";
+
+ $sql = sprintf("CREATE TABLE test(id INT AUTO_INCREMENT PRIMARY KEY, col1 %s) ENGINE=%s",
+ $column, $engine);
+ if (!mysqli_query($link, $sql)) {
+ printf("[%03d] Cannot create table test, [%d] %s\n",
+ $offset + 1,
+ mysqli_errno($link), mysqli_error($link));
+ return array();
+ }
+
+ $values = array();
+ for ($i = 1; $i <= 100; $i++) {
+ $col1 = mt_rand($min, $max);
+ $values[$i] = $col1;
+ $sql = sprintf("INSERT INTO test(id, col1) VALUES (%d, %f)",
+ $i, $col1);
+ if (!mysqli_query($link, $sql)) {
+ printf("[%03d] Cannot insert data, [%d] %s\n",
+ $offset + 2,
+ mysqli_errno($link), mysqli_error($link));
+ return array();
+ }
+ }
+
+ return $values;
+ }
+
+ function test_format($link, $format, $from, $order_by, $expected, $offset) {
+
+ if (!$stmt = mysqli_stmt_init($link)) {
+ printf("[%03d] Cannot create PS, [%d] %s\n",
+ $offset,
+ mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+ print "$format\n";
+
+ if ($order_by)
+ $sql = sprintf('SELECT %s AS _format FROM %s ORDER BY %s', $format, $from, $order_by);
+ else
+ $sql = sprintf('SELECT %s AS _format FROM %s', $format, $from);
+
+ if (!mysqli_stmt_prepare($stmt, $sql)) {
+ printf("[%03d] Cannot prepare PS, [%d] %s\n",
+ $offset + 1,
+ mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ return false;
+ }
+
+ if (!mysqli_stmt_execute($stmt)) {
+ printf("[%03d] Cannot execute PS, [%d] %s\n",
+ $offset + 2,
+ mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ return false;
+ }
+
+ if (!mysqli_stmt_store_result($stmt)) {
+ printf("[%03d] Cannot store result set, [%d] %s\n",
+ $offset + 3,
+ mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ return false;
+ }
+
+ if (!is_array($expected)) {
+
+ $result = null;
+ if (!mysqli_stmt_bind_result($stmt, $result)) {
+ printf("[%03d] Cannot bind result, [%d] %s\n",
+ $offset + 4,
+ mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ return false;
+ }
+
+ if (!mysqli_stmt_fetch($stmt)) {
+ printf("[%03d] Cannot fetch result,, [%d] %s\n",
+ $offset + 5,
+ mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ return false;
+ }
+
+ if ($result !== $expected) {
+ printf("[%03d] Expecting %s/%s got %s/%s with %s - %s.\n",
+ $offset + 6,
+ gettype($expected), $expected,
+ gettype($result), $result,
+ $format, $sql);
+ }
+
+ } else {
+
+ $order_by_col = $result = null;
+ if (!is_null($order_by)) {
+ if (!mysqli_stmt_bind_result($stmt, $order_by_col, $result)) {
+ printf("[%03d] Cannot bind result, [%d] %s\n",
+ $offset + 7,
+ mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ return false;
+ }
+ } else {
+ if (!mysqli_stmt_bind_result($stmt, $result)) {
+ printf("[%03d] Cannot bind result, [%d] %s\n",
+ $offset + 7,
+ mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ return false;
+ }
+ }
+
+ if (!empty($expected))
+ reset($expected);
+ while ((list($k, $v) = each($expected)) && mysqli_stmt_fetch($stmt)) {
+ if (!empty($expected)) {
+ if ($result !== $v) {
+ printf("[%03d] Row %d - expecting %s/%s got %s/%s [%s] with %s - %s.\n",
+ $offset + 8,
+ $k,
+ gettype($v), $v,
+ gettype($result), $result,
+ $order_by_col,
+ $format, $sql);
+ }
+ }
+ }
+
+ }
+
+ mysqli_stmt_free_result($stmt);
+ mysqli_stmt_close($stmt);
+
+ return true;
+ }
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[001] Cannot connect - [%d] %s\n",
+ mysqli_connect_errno(),
+ mysqli_connect_error());
+
+ /* create new table and select from it */
+ $expected = create_table($link, 'FLOAT', -10000, 10000, $engine, 90);
+ foreach ($expected as $k => $v)
+ $expected[$k] = number_format(round($v), 0, '.', ',');
+ test_format($link, 'FORMAT(col1, 0)', 'test', NULL, array(), 100);
+
+ $expected = create_table($link, 'FLOAT', -10000, 10000, $engine, 110);
+ foreach ($expected as $k => $v)
+ $expected[$k] = number_format(round($v), 0, '.', ',');
+ test_format($link, 'id AS order_by_col, FORMAT(col1, 0)', 'test', 'id', $expected, 120);
+
+ $expected = create_table($link, 'FLOAT UNSIGNED', 0, 10000, $engine, 130);
+ foreach ($expected as $k => $v)
+ $expected[$k] = number_format(round($v), 0, '.', ',');
+ test_format($link, 'id AS order_by_col, FORMAT(col1, 0)', 'test', 'id', $expected, 140);
+
+ $expected = create_table($link, 'DECIMAL(5,0)', -1000, 1000, $engine, 150);
+ foreach ($expected as $k => $v)
+ $expected[$k] = number_format(round($v), 0, '.', ',');
+ test_format($link, 'id AS order_by_col, FORMAT(col1, 0)', 'test', 'id', $expected, 160);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+FLOAT
+FORMAT(col1, 0)
+FLOAT
+id AS order_by_col, FORMAT(col1, 0)
+FLOAT UNSIGNED
+id AS order_by_col, FORMAT(col1, 0)
+DECIMAL(5,0)
+id AS order_by_col, FORMAT(col1, 0)
+done!
diff --git a/ext/mysqli/tests/bug42548.phpt b/ext/mysqli/tests/bug42548.phpt
new file mode 100644
index 0000000..ef0c831
--- /dev/null
+++ b/ext/mysqli/tests/bug42548.phpt
@@ -0,0 +1,75 @@
+--TEST--
+Bug #42548 PROCEDURE xxx can't return a result set in the given context (works in 5.2.3!!)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+require_once('connect.inc');
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ die(sprintf('skip Cannot connect to MySQL, [%d] %s.', mysqli_connect_errno(), mysqli_connect_error()));
+}
+if (mysqli_get_server_version($link) <= 50000) {
+ die(sprintf('skip Needs MySQL 5.0+, found version %d.', mysqli_get_server_version($link)));
+}
+?>
+--FILE--
+<?php
+require_once('connect.inc');
+
+$mysqli = mysqli_init();
+$mysqli->real_connect($host, $user, $passwd, $db, $port, $socket);
+if (mysqli_connect_errno()) {
+ printf("Connect failed: %s\n", mysqli_connect_error());
+ exit();
+}
+
+$mysqli->query("DROP PROCEDURE IF EXISTS p1") or die($mysqli->error);
+$mysqli->query("CREATE PROCEDURE p1() BEGIN SELECT 23; SELECT 42; END") or die($mysqli->error);
+
+if ($mysqli->multi_query("CALL p1();"))
+{
+ do
+ {
+ if ($objResult = $mysqli->store_result()) {
+ while ($row = $objResult->fetch_assoc()) {
+ print_r($row);
+ }
+ $objResult->close();
+ if ($mysqli->more_results()) {
+ print "----- next result -----------\n";
+ }
+ } else {
+ print "no results found\n";
+ }
+ } while ($mysqli->more_results() && $mysqli->next_result());
+} else {
+ print $mysqli->error;
+}
+
+$mysqli->query("DROP PROCEDURE p1") or die($mysqli->error);
+$mysqli->close();
+print "done!";
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+mysqli_query($link, "DROP PROCEDURE IF EXISTS p1");
+
+mysqli_close($link);
+?>
+--EXPECT--
+Array
+(
+ [23] => 23
+)
+----- next result -----------
+Array
+(
+ [42] => 42
+)
+----- next result -----------
+no results found
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/bug44897.phpt b/ext/mysqli/tests/bug44897.phpt
new file mode 100644
index 0000000..84c245d
--- /dev/null
+++ b/ext/mysqli/tests/bug44897.phpt
@@ -0,0 +1,89 @@
+--TEST--
+Bug #44879 (failed to prepare statement)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+
+if (!stristr(mysqli_get_client_info(), 'mysqlnd'))
+ die("skip: only available in mysqlnd");
+
+require_once('skipifconnectfailure.inc');
+require_once('connect.inc');
+
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ die(sprintf('skip Cannot connect to MySQL, [%d] %s.', mysqli_connect_errno(), mysqli_connect_error()));
+}
+if (mysqli_get_server_version($link) <= 50000) {
+ die(sprintf('skip Needs MySQL 5.0+, found version %d.', mysqli_get_server_version($link)));
+}
+?>
+--FILE--
+<?php
+ require_once("table.inc");
+
+ if (!$link->query('DROP PROCEDURE IF EXISTS p'))
+ printf("[001] [%d] %s\n", $link->errno, $link->error);
+
+ if (!$link->query('CREATE PROCEDURE p(IN new_id INT, IN new_label CHAR(1)) BEGIN INSERT INTO test(id, label) VALUES (new_id, new_label); SELECT new_label; END;'))
+ printf("[002] [%d] %s\n", $link->errno, $link->error);
+
+ $new_id = 100;
+ $new_label = 'z';
+
+ if (!$stmt = $link->prepare('CALL p(?, ?)'))
+ printf("[003] [%d] %s\n", $link->errno, $link->error);
+
+ if (!$stmt->bind_param('is', $new_id, $new_label) || !$stmt->execute())
+ printf("[004] [%d] %s\n", $stmt->errno, $stmt->error);
+
+ $out_new_label = null;
+ if (!$stmt->bind_result($out_new_label) || !$stmt->fetch())
+ printf("[005] [%d] %s\n", $stmt->errno, $stmt->error);
+
+ if ($out_new_label != $new_label)
+ printf("[006] IN value and returned value differ. Expecting %s/%s got %s/%s\n",
+ $new_label, gettype($new_label), $out_new_label, gettype($out_new_label));
+
+ $stmt->close();
+
+ $stmt2 = $link->prepare('SELECT label FROM test WHERE id = ?');
+ if (!is_object($stmt2)) {
+
+ printf("[007] Failed to create new statement object, [%d] %s\n",
+ $link->errno, $link->error);
+
+ } else {
+
+ if (!$stmt2->bind_param("i", $new_id) || !$stmt2->execute())
+ printf("[008] [%d] %s\n", $stmt2->errno, $stmt2->error);
+
+ $out_new_label = null;
+ if (!$stmt2->bind_result($out_new_label) || !$stmt2->fetch())
+ printf("[009] [%d] %s\n", $stmt2->errno, $stmt2->error);
+
+ if ($out_new_label != $new_label)
+ printf("[010] IN value and returned value differ. Expecting %s/%s got %s/%s\n",
+ $new_label, gettype($new_label), $out_new_label, gettype($out_new_label));
+
+ }
+
+ $link->close();
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS test"))
+ printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+mysqli_query($link, "DROP PROCEDURE IF EXISTS p");
+
+mysqli_close($link);
+?>
+
+--EXPECTF--
+done!
diff --git a/ext/mysqli/tests/bug45019.phpt b/ext/mysqli/tests/bug45019.phpt
new file mode 100644
index 0000000..b8828c7
--- /dev/null
+++ b/ext/mysqli/tests/bug45019.phpt
@@ -0,0 +1,59 @@
+--TEST--
+Bug #45019 (Segmentation fault with SELECT ? and UNION)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+ require_once("table.inc");
+
+ // Regular (non-prepared) queries
+ print "Using CAST('somestring' AS CHAR)...\n";
+ if (!($res = $link->query("SELECT CAST('one' AS CHAR) AS column1 UNION SELECT CAST('three' AS CHAR) UNION SELECT CAST('two' AS CHAR)")))
+ printf("[001] [%d] %s\n", $link->errno, $link->error);
+
+ $data = array();
+ while ($row = $res->fetch_assoc()) {
+ $data[] = $row['column1'];
+ var_dump($row['column1']);
+ }
+ $res->free();
+
+ // Prepared Statements
+ if (!($stmt = $link->prepare("SELECT CAST('one' AS CHAR) AS column1 UNION SELECT CAST('three' AS CHAR) UNION SELECT CAST('two' AS CHAR)")))
+ printf("[002] [%d] %s\n", $link->errno, $link->error);
+
+ $column1 = null;
+ if (!$stmt->bind_result($column1) || !$stmt->execute())
+ printf("[003] [%d] %s\n", $stmt->errno, $stmt->error);
+
+ $index = 0;
+ while ($stmt->fetch()) {
+ /* NOTE: libmysql - http://bugs.mysql.com/bug.php?id=47483 */
+ if ($data[$index] != $column1) {
+ if ($IS_MYSQLND || $index != 1) {
+ printf("[004] Row %d, expecting %s/%s got %s/%s\n",
+ $index + 1, gettype($data[$index]), $data[$index], gettype($column1), $column1);
+ } else {
+ if ($column1 != "thre")
+ printf("[005] Got '%s'. Please check if http://bugs.mysql.com/bug.php?id=47483 has been fixed and adapt tests bug45019.phpt/mysqli_ps_select_union.phpt", $column1);
+ }
+ }
+ $index++;
+ }
+ $stmt->close();
+
+ $link->close();
+
+ print "done!";
+?>
+--EXPECTF--
+Using CAST('somestring' AS CHAR)...
+%unicode|string%(3) "one"
+%unicode|string%(5) "three"
+%unicode|string%(3) "two"
+done!
diff --git a/ext/mysqli/tests/bug45289.phpt b/ext/mysqli/tests/bug45289.phpt
new file mode 100644
index 0000000..2ddacf4
--- /dev/null
+++ b/ext/mysqli/tests/bug45289.phpt
@@ -0,0 +1,40 @@
+--TEST--
+Bug #45289 (Bogus store_result on PS)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require('table.inc');
+
+ $link->close();
+
+ $link = mysqli_init();
+ if (!($link->real_connect($host, $user, $passwd, $db, $port, $socket)))
+ printf("[001] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ $id = 1;
+ if (!($stmt = $link->prepare('SELECT id, label FROM test WHERE id=? LIMIT 1')))
+ printf("[002] [%d] %s\n", $link->errno, $link->error);
+
+ if (!$stmt->bind_param('i', $id) || !$stmt->execute())
+ printf("[003] [%d] %s\n", $stmt->errno, $stmt->error);
+
+ if ($res = $link->store_result()) {
+ if ($IS_MYSQLND)
+ printf("[004] Can store result!\n");
+ else
+ printf("[004] [007] http://bugs.mysql.com/bug.php?id=47485\n");
+ } else {
+ printf("[004] [%d] %s\n", $link->errno, $link->error);
+ }
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+[004] [%s
diff --git a/ext/mysqli/tests/bug46109.phpt b/ext/mysqli/tests/bug46109.phpt
new file mode 100644
index 0000000..c377171
--- /dev/null
+++ b/ext/mysqli/tests/bug46109.phpt
@@ -0,0 +1,18 @@
+--TEST--
+Bug #46109 (MySQLi::init - Memory leaks)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $mysqli = new mysqli();
+ $mysqli->init();
+ $mysqli->init();
+ echo "done";
+?>
+--EXPECTF--
+done
diff --git a/ext/mysqli/tests/bug46614.phpt b/ext/mysqli/tests/bug46614.phpt
new file mode 100644
index 0000000..9e78222
--- /dev/null
+++ b/ext/mysqli/tests/bug46614.phpt
@@ -0,0 +1,30 @@
+--TEST--
+Bug #46614 (Extended MySQLi class gives incorrect empty() result)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+if (!defined("MYSQLI_ASYNC")) {
+ die("skip mysqlnd only");
+}
+?>
+--FILE--
+<?php
+class MySQL_Ext extends mysqli{
+ protected $fooData = array();
+
+ public function isEmpty()
+ {
+ $this->extData[] = 'Bar';
+ return empty($this->extData);
+ }
+}
+
+include ("connect.inc");
+$MySQL_Ext = new MySQL_Ext($host, $user, $passwd, $db, $port, $socket);
+
+$isEmpty = $MySQL_Ext->isEmpty();
+var_dump($isEmpty);
+?>
+--EXPECT--
+bool(false)
diff --git a/ext/mysqli/tests/bug47050.phpt b/ext/mysqli/tests/bug47050.phpt
new file mode 100644
index 0000000..0358802
--- /dev/null
+++ b/ext/mysqli/tests/bug47050.phpt
@@ -0,0 +1,34 @@
+--TEST--
+Bug #47050 (mysqli_poll() modifies improper variables)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+if (!defined("MYSQLI_ASYNC")) {
+ die("skip mysqlnd only");
+}
+?>
+--FILE--
+<?php
+ include ("connect.inc");
+
+ $link1 = my_mysqli_connect($host, $user, $passwd, null, $port, $socket);
+ mysqli_select_db($link1, $db);
+
+ $link1->query("SELECT 'test'", MYSQLI_ASYNC);
+ $all_links = array($link1);
+ $links = $errors = $reject = $all_links;
+ mysqli_poll($links, $errors, $reject, 1);
+
+ echo "links: ", sizeof($links), "\n";
+ echo "errors: ", sizeof($errors), "\n";
+ echo "reject: ", sizeof($reject), "\n";
+ echo "all_links: ", sizeof($all_links), "\n";
+
+ $link1->close();
+?>
+--EXPECT--
+links: 1
+errors: 0
+reject: 0
+all_links: 1
diff --git a/ext/mysqli/tests/bug48909.phpt b/ext/mysqli/tests/bug48909.phpt
new file mode 100644
index 0000000..7690139
--- /dev/null
+++ b/ext/mysqli/tests/bug48909.phpt
@@ -0,0 +1,46 @@
+--TEST--
+Bug #48909 (Segmentation fault in mysqli_stmt_execute)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ if (!($link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)))
+ printf("[001] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ if (!$link->query("DROP TABLE IF EXISTS test") ||
+ !$link->query(sprintf("CREATE TABLE test(id INT, label varchar(255)) ENGINE = %s", $engine)))
+ printf("[002] [%d] %s\n", $link->errno, $link->error);
+
+ if (!$stmt = $link->prepare("INSERT INTO test(id, label) VALUES (?, ?)"))
+ printf("[003] [%d] %s\n", $link->errno, $link->error);
+
+ if (!$stmt->bind_param("bb",$bvar, $bvar))
+ printf("[004] [%d] %s\n", $stmt->errno, $stmt->error);
+
+ if (!$stmt->execute()) {
+ if ($stmt->errno != 1366) {
+ /*
+ $bvar is null, b is for BLOB - any error like this should be OK:
+ 1366 - Incorrect integer value: '' for column 'id' at row 1
+ */
+ printf("[005] [%d] %s\n", $stmt->errno, $stmt->error);
+ }
+ }
+
+ $stmt->close();
+ $link->close();
+
+ echo "done";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+done \ No newline at end of file
diff --git a/ext/mysqli/tests/bug49027.phpt b/ext/mysqli/tests/bug49027.phpt
new file mode 100644
index 0000000..35434bd
--- /dev/null
+++ b/ext/mysqli/tests/bug49027.phpt
@@ -0,0 +1,62 @@
+--TEST--
+Bug #49027 (mysqli_options() doesn't work when using mysqlnd)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ include ("connect.inc");
+
+ $link = mysqli_init();
+ if (!mysqli_options($link, MYSQLI_INIT_COMMAND, "SELECT 1")) {
+ printf("[001] Cannot set INIT_COMMAND\n");
+ }
+
+ if (!my_mysqli_real_connect($link, $host, $user, $passwd, $db, $port, $socket)) {
+ printf("[002] Connect failed, [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+ }
+
+ var_dump($link->query("SELECT 42")->fetch_row());
+
+ if (!mysqli_query($link, "DROP TABLE IF EXISTS test") ||
+ !mysqli_query($link, sprintf("CREATE TABLE test(id INT) ENGINE=%s", $engine))) {
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ mysqli_close($link);
+
+ $link = mysqli_init();
+ if (!mysqli_options($link, MYSQLI_INIT_COMMAND, "INSERT INTO test(id) VALUES(1)")) {
+ printf("[004] Cannot set INIT_COMMAND\n");
+ }
+
+ if (!my_mysqli_real_connect($link, $host, $user, $passwd, $db, $port, $socket)) {
+ printf("[005] Connect failed, [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+ }
+
+ if (!$res = mysqli_query($link, "SELECT id FROM test"))
+ printf("[006] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ var_dump(mysqli_fetch_assoc($res));
+
+ mysqli_free_result($res);
+ mysqli_close($link);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+array(1) {
+ [0]=>
+ %unicode|string%(2) "42"
+}
+array(1) {
+ [%u|b%"id"]=>
+ %unicode|string%(1) "1"
+}
+done!
diff --git a/ext/mysqli/tests/bug49442.phpt b/ext/mysqli/tests/bug49442.phpt
new file mode 100644
index 0000000..5426745
--- /dev/null
+++ b/ext/mysqli/tests/bug49442.phpt
@@ -0,0 +1,130 @@
+--TEST--
+Bug #49422 (mysqlnd: mysqli_real_connect() and LOAD DATA INFILE crash)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+
+$link = mysqli_init();
+if (!my_mysqli_real_connect($link, $host, $user, $passwd, $db, $port, $socket)) {
+ die(sprintf("skip Connect failed, [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()));
+}
+
+include_once("local_infile_tools.inc");
+if ($msg = check_local_infile_support($link, $engine))
+ die(sprintf("skip %s, [%d] %s", $msg, $link->errno, $link->error));
+
+mysqli_close($link);
+?>
+--INI--
+mysqli.allow_local_infile=1
+mysqli.allow_persistent=1
+mysqli.max_persistent=1
+--FILE--
+<?php
+ include ("connect.inc");
+
+ $link = mysqli_init();
+ if (!my_mysqli_real_connect($link, $host, $user, $passwd, $db, $port, $socket)) {
+ printf("[001] Connect failed, [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+ }
+
+ if (!mysqli_query($link, 'DROP TABLE IF EXISTS test')) {
+ printf("[002] Failed to drop old test table: [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ if (!mysqli_query($link, 'CREATE TABLE test(id INT, label CHAR(1), PRIMARY KEY(id)) ENGINE=' . $engine)) {
+ printf("[003] Failed to create test table: [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ include("local_infile_tools.inc");
+ $file = create_standard_csv(4);
+
+ if (!@mysqli_query($link, sprintf("LOAD DATA LOCAL INFILE '%s'
+ INTO TABLE test
+ FIELDS TERMINATED BY ';' OPTIONALLY ENCLOSED BY '\''
+ LINES TERMINATED BY '\n'",
+ mysqli_real_escape_string($link, $file)))) {
+ printf("[005] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ if (!$res = mysqli_query($link, "SELECT * FROM test ORDER BY id"))
+ printf("[006] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $rows = array();
+ while ($row = mysqli_fetch_assoc($res)) {
+ var_dump($row);
+ $rows[] = $row;
+ }
+
+ mysqli_free_result($res);
+
+ mysqli_query($link, "DELETE FROM test");
+ mysqli_close($link);
+
+ if ($IS_MYSQLND) {
+ /*
+ mysqlnd makes a connection created through mysql_init()/mysqli_real_connect() always a 'persistent' one.
+ At this point 'persistent' is not to be confused with what a user calls a 'persistent' - in this case
+ 'persistent' means that mysqlnd uses malloc() instead of emalloc(). nothing else. ext/mysqli will
+ not consider it as a 'persistent' connection in a user sense, ext/mysqli will not appy max_persistent etc.
+ Its only about malloc() vs. emalloc().
+
+ However, the bug is about malloc() and efree(). You can make make mysqlnd use malloc() by either using
+ pconnect or mysql_init() - so we should test pconnect as well..
+ */
+ $host = 'p:' . $host;
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ printf("[007] Connect failed, [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+ }
+
+ /* bug happened during query processing */
+ if (!@mysqli_query($link, sprintf("LOAD DATA LOCAL INFILE '%s'
+ INTO TABLE test
+ FIELDS TERMINATED BY ';' OPTIONALLY ENCLOSED BY '\''
+ LINES TERMINATED BY '\n'",
+ mysqli_real_escape_string($link, $file)))) {
+ printf("[008] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ /* we survived? that's good enough... */
+
+ if (!$res = mysqli_query($link, "SELECT * FROM test ORDER BY id"))
+ printf("[009] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $i = 0;
+ while ($row = mysqli_fetch_assoc($res)) {
+ if (($row['id'] != $rows[$i]['id']) || ($row['label'] != $rows[$i]['label'])) {
+ printf("[010] Wrong values, check manually!\n");
+ }
+ $i++;
+ }
+ mysqli_close($link);
+ }
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+array(2) {
+ [%u|b%"id"]=>
+ %unicode|string%(2) "97"
+ [%u|b%"label"]=>
+ %unicode|string%(1) "x"
+}
+array(2) {
+ [%u|b%"id"]=>
+ %unicode|string%(2) "98"
+ [%u|b%"label"]=>
+ %unicode|string%(1) "y"
+}
+array(2) {
+ [%u|b%"id"]=>
+ %unicode|string%(2) "99"
+ [%u|b%"label"]=>
+ %unicode|string%(1) "z"
+}
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/bug50772.phpt b/ext/mysqli/tests/bug50772.phpt
new file mode 100644
index 0000000..eecef84
--- /dev/null
+++ b/ext/mysqli/tests/bug50772.phpt
@@ -0,0 +1,36 @@
+--TEST--
+Bug #50772 (mysqli constructor without parameters does not return a working mysqli object)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ include "connect.inc";
+ $db1 = new mysqli();
+
+ // These calls fail
+ $db1->options(MYSQLI_OPT_CONNECT_TIMEOUT, 3);
+ my_mysqli_real_connect($db1, $host, $user, $passwd, $db, $port, $socket);
+ if(mysqli_connect_error()) {
+ echo "error 1\n";
+ } else {
+ echo "ok 1\n";
+ }
+
+ $db2 = mysqli_init();
+
+ $db2->options(MYSQLI_OPT_CONNECT_TIMEOUT, 3);
+ my_mysqli_real_connect($db2, $host, $user, $passwd, $db, $port, $socket);
+ if(mysqli_connect_error()) {
+ echo "error 2\n";
+ } else {
+ echo "ok 2\n";
+ }
+ echo "done\n";
+?>
+--EXPECTF--
+ok 1
+ok 2
+done \ No newline at end of file
diff --git a/ext/mysqli/tests/bug51605.phpt b/ext/mysqli/tests/bug51605.phpt
new file mode 100644
index 0000000..02328a5
--- /dev/null
+++ b/ext/mysqli/tests/bug51605.phpt
@@ -0,0 +1,44 @@
+--TEST--
+Bug #51605 Mysqli - zombie links
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--INI--
+mysqli.max_links = 1
+mysqli.allow_persistent = Off
+mysqli.max_persistent = 0
+mysqli.reconnect = Off
+--FILE--
+<?php
+ include ("connect.inc");
+
+ $link = mysqli_init();
+ if (!my_mysqli_real_connect($link, $host, $user, $passwd, $db, $port, $socket)) {
+ printf("[002] Connect failed, [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+ }
+ mysqli_close($link);
+ echo "closed once\n";
+
+ $link = mysqli_init();
+ if (!my_mysqli_real_connect($link, $host, $user, $passwd, $db, $port, $socket)) {
+ printf("[002] Connect failed, [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+ }
+ mysqli_close($link);
+ echo "closed twice\n";
+
+ $link = mysqli_init();
+ if (!my_mysqli_real_connect($link, $host, $user, $passwd, $db, $port, $socket)) {
+ printf("[003] Connect failed, [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+ }
+ mysqli_close($link);
+ echo "closed for third time\n";
+
+ print "done!";
+?>
+--EXPECTF--
+closed once
+closed twice
+closed for third time
+done!
diff --git a/ext/mysqli/tests/bug51647.phpt b/ext/mysqli/tests/bug51647.phpt
new file mode 100644
index 0000000..78540f1
--- /dev/null
+++ b/ext/mysqli/tests/bug51647.phpt
@@ -0,0 +1,81 @@
+--TEST--
+Bug #51647 (Certificate file without private key (pk in another file) doesn't work)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+require_once("connect.inc");
+
+if ($IS_MYSQLND && !extension_loaded("openssl"))
+ die("skip PHP streams lack support for SSL. mysqli is compiled to use mysqlnd which uses PHP streams in turn.");
+
+if (!($link = @my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)))
+ die(sprintf("skip Connect failed, [%d] %s", mysqli_connect_errno(), mysqli_connect_error()));
+
+$row = NULL;
+if ($res = $link->query('SHOW VARIABLES LIKE "have_ssl"')) {
+ $row = $res->fetch_row();
+} else {
+ if ($link->errno == 1064 && ($res = $link->query("SHOW VARIABLES"))) {
+ while ($row = $res->fetch_row())
+ if ($row[0] == 'have_ssl')
+ break;
+ } else {
+ die(sprintf("skip Failed to test for MySQL SSL support, [%d] %s", $link->errno, $link->error));
+ }
+}
+
+
+if (empty($row))
+ die(sprintf("skip Failed to test for MySQL SSL support, [%d] %s", $link->errno, $link->error));
+
+if (($row[1] == 'NO') || ($row[1] == 'DISABLED'))
+ die(sprintf("skip MySQL has no SSL support, [%d] %s", $link->errno, $link->error));
+
+$link->close();
+?>
+--FILE--
+<?php
+ include ("connect.inc");
+
+ if (!is_object($link = mysqli_init()))
+ printf("[001] Cannot create link\n");
+
+ $path_to_pems = !$IS_MYSQLND? "ext/mysqli/tests/" : "";
+ if (!$link->ssl_set("{$path_to_pems}client-key.pem", "{$path_to_pems}client-cert.pem", "{$path_to_pems}cacert.pem","",""))
+ printf("[002] [%d] %s\n", $link->errno, $link->error);
+
+ if (!my_mysqli_real_connect($link, $host, $user, $passwd, $db, $port, $socket)) {
+ printf("[003] Connect failed, [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+ }
+
+ if (!$res = $link->query('SHOW STATUS like "Ssl_cipher"')) {
+ if (1064 == $link->errno) {
+ /* ERROR 1064 (42000): You have an error in your SQL syntax; = sql strict mode */
+ if ($res = $link->query("SHOW STATUS")) {
+ while ($row = $res->fetch_assoc())
+ if ($row['Variable_name'] == 'Ssl_cipher')
+ break;
+ } else {
+ printf("[005] [%d] %s\n", $link->errno, $link->error);
+ }
+ } else {
+ printf("[004] [%d] %s\n", $link->errno, $link->error);
+ }
+ } else {
+ if (!$row = $res->fetch_assoc())
+ printf("[006] [%d] %s\n", $link->errno, $link->error);
+ }
+
+ var_dump($row);
+
+ print "done!";
+?>
+--EXPECTF--
+array(2) {
+ ["Variable_name"]=>
+ string(10) "Ssl_cipher"
+ ["Value"]=>
+ string(%d) "%S"
+}
+done!
diff --git a/ext/mysqli/tests/bug52082.phpt b/ext/mysqli/tests/bug52082.phpt
new file mode 100644
index 0000000..8e3bd59
--- /dev/null
+++ b/ext/mysqli/tests/bug52082.phpt
@@ -0,0 +1,50 @@
+--TEST--
+Bug #52082 (character_set_client & character_set_connection reset after mysqli_change_user)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+ $link = mysqli_init();
+ $link->options(MYSQLI_SET_CHARSET_NAME, "latin2");
+ if (!my_mysqli_real_connect($link, $host, $user, $passwd, $db, $port, $socket)) {
+ die("can't connect");
+ }
+ var_dump($link->query("show variables like 'character_set_client'")->fetch_row());
+ var_dump($link->query("show variables like 'character_set_connection'")->fetch_row());
+ $link->change_user($user, $passwd, $db);
+ var_dump($link->query("show variables like 'character_set_client'")->fetch_row());
+ var_dump($link->query("show variables like 'character_set_connection'")->fetch_row());
+
+ print "done!";
+?>
+--EXPECTF--
+array(2) {
+ [0]=>
+ string(20) "character_set_client"
+ [1]=>
+ string(6) "latin2"
+}
+array(2) {
+ [0]=>
+ string(24) "character_set_connection"
+ [1]=>
+ string(6) "latin2"
+}
+array(2) {
+ [0]=>
+ string(20) "character_set_client"
+ [1]=>
+ string(6) "latin2"
+}
+array(2) {
+ [0]=>
+ string(24) "character_set_connection"
+ [1]=>
+ string(6) "latin2"
+}
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/bug52891.phpt b/ext/mysqli/tests/bug52891.phpt
new file mode 100644
index 0000000..463efd6
--- /dev/null
+++ b/ext/mysqli/tests/bug52891.phpt
@@ -0,0 +1,160 @@
+--TEST--
+Bug #52891 (Wrong data inserted with mysqli/mysqlnd when using bind_param,value > LONG_MAX)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+if (!$IS_MYSQLND) {
+ die("skip: test applies only to mysqlnd");
+}
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ printf("[001] Connect failed, [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+ }
+
+ if (!$link->query("DROP TABLE IF EXISTS tuint") ||
+ !$link->query("DROP TABLE IF EXISTS tsint")) {
+ printf("[002] [%d] %s\n", $link->errno, $link->error);
+ }
+
+ if (!$link->query("CREATE TABLE tuint(a BIGINT UNSIGNED) ENGINE=" . $engine) ||
+ !$link->query("CREATE TABLE tsint(a BIGINT) ENGINE=" . $engine)) {
+ printf("[003] [%d] %s\n", $link->errno, $link->error);
+ }
+
+
+ if (!$stmt1 = $link->prepare("INSERT INTO tuint VALUES(?)"))
+ printf("[004] [%d] %s\n", $link->errno, $link->error);
+
+ if (!$stmt2 = $link->prepare("INSERT INTO tsint VALUES(?)"))
+ printf("[005] [%d] %s\n", $link->errno, $link->error);
+
+ $param = 42;
+
+ if (!$stmt1->bind_param("i", $param))
+ printf("[006] [%d] %s\n", $stmt1->errno, $stmt1->error);
+
+ if (!$stmt2->bind_param("i", $param))
+ printf("[007] [%d] %s\n", $stmt2->errno, $stmt2->error);
+
+ /* first insert normal value to force initial send of types */
+ if (!$stmt1->execute())
+ printf("[008] [%d] %s\n", $stmt1->errno, $stmt1->error);
+
+ if (!$stmt2->execute())
+ printf("[009] [%d] %s\n", $stmt2->errno, $stmt2->error);
+
+ /* now try values that don't fit in long, on 32bit, new types should be sent or 0 will be inserted */
+ $param = -4294967297;
+ if (!$stmt2->execute())
+ printf("[010] [%d] %s\n", $stmt2->errno, $stmt2->error);
+
+ /* again normal value */
+ $param = 43;
+
+ if (!$stmt1->execute())
+ printf("[011] [%d] %s\n", $stmt1->errno, $stmt1->error);
+
+ if (!$stmt2->execute())
+ printf("[012] [%d] %s\n", $stmt2->errno, $stmt2->error);
+
+ /* again conversion */
+ $param = -4294967295;
+ if (!$stmt2->execute())
+ printf("[013] [%d] %s\n", $stmt2->errno, $stmt2->error);
+
+ $param = 4294967295;
+ if (!$stmt1->execute())
+ printf("[014] [%d] %s\n", $stmt1->errno, $stmt1->error);
+
+ if (!$stmt2->execute())
+ printf("[015] [%d] %s\n", $stmt2->errno, $stmt2->error);
+
+ $param = 4294967297;
+ if (!$stmt1->execute())
+ printf("[016] [%d] %s\n", $stmt1->errno, $stmt1->error);
+
+ if (!$stmt2->execute())
+ printf("[017] [%d] %s\n", $stmt2->errno, $stmt2->error);
+
+ $result = $link->query("SELECT * FROM tsint ORDER BY a ASC");
+ $result2 = $link->query("SELECT * FROM tuint ORDER BY a ASC");
+
+ echo "tsint:\n";
+ while ($row = $result->fetch_assoc()) {
+ var_dump($row);
+ }
+ echo "tuint:\n";
+ while ($row = $result2->fetch_assoc()) {
+ var_dump($row);
+ }
+
+ echo "done";
+?>
+--CLEAN--
+<?php
+require_once('connect.inc');
+
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ printf("[clean] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+}
+
+if (!mysqli_query($link, 'DROP TABLE IF EXISTS tuint')) {
+ printf("[clean] Failed to drop old test table: [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+}
+
+if (!mysqli_query($link, 'DROP TABLE IF EXISTS tsint')) {
+ printf("[clean] Failed to drop old test table: [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+}
+
+mysqli_close($link);
+?>
+--EXPECTF--
+tsint:
+array(1) {
+ ["a"]=>
+ string(11) "-4294967297"
+}
+array(1) {
+ ["a"]=>
+ string(11) "-4294967295"
+}
+array(1) {
+ ["a"]=>
+ string(2) "42"
+}
+array(1) {
+ ["a"]=>
+ string(2) "43"
+}
+array(1) {
+ ["a"]=>
+ string(10) "4294967295"
+}
+array(1) {
+ ["a"]=>
+ string(10) "4294967297"
+}
+tuint:
+array(1) {
+ ["a"]=>
+ string(2) "42"
+}
+array(1) {
+ ["a"]=>
+ string(2) "43"
+}
+array(1) {
+ ["a"]=>
+ string(10) "4294967295"
+}
+array(1) {
+ ["a"]=>
+ string(10) "4294967297"
+}
+done \ No newline at end of file
diff --git a/ext/mysqli/tests/bug53503.phpt b/ext/mysqli/tests/bug53503.phpt
new file mode 100644
index 0000000..339fce7
--- /dev/null
+++ b/ext/mysqli/tests/bug53503.phpt
@@ -0,0 +1,66 @@
+--TEST--
+Bug #53503 (mysqli::query returns false after successful LOAD DATA query)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ die("skip Cannot connect to MySQL");
+
+include_once("local_infile_tools.inc");
+if ($msg = check_local_infile_support($link, $engine))
+ die(sprintf("skip %s, [%d] %s", $msg, $link->errno, $link->error));
+
+mysqli_close($link);
+
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ printf("[001] Connect failed, [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+ }
+
+ if (!$link->query("DROP TABLE IF EXISTS test")) {
+ printf("[002] [%d] %s\n", $link->errno, $link->error);
+ }
+
+ if (!$link->query("CREATE TABLE test (dump1 INT UNSIGNED NOT NULL PRIMARY KEY) ENGINE=" . $engine)) {
+ printf("[003] [%d] %s\n", $link->errno, $link->error);
+ }
+
+ if (FALSE == file_put_contents('bug53503.data', "1\n2\n3\n"))
+ printf("[004] Failed to create CVS file\n");
+
+ if (!$link->query("SELECT 1 FROM DUAL"))
+ printf("[005] [%d] %s\n", $link->errno, $link->error);
+
+ if (!$link->query("LOAD DATA LOCAL INFILE 'bug53503.data' INTO TABLE test")) {
+ printf("[006] [%d] %s\n", $link->errno, $link->error);
+ echo "bug";
+ } else {
+ echo "done";
+ }
+ $link->close();
+?>
+--CLEAN--
+<?php
+require_once('connect.inc');
+
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ printf("[clean] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+}
+
+if (!$link->query($link, 'DROP TABLE IF EXISTS test')) {
+ printf("[clean] Failed to drop old test table: [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+}
+
+$link->close();
+
+unlink('bug53503.data');
+?>
+--EXPECT--
+done \ No newline at end of file
diff --git a/ext/mysqli/tests/bug54221.phpt b/ext/mysqli/tests/bug54221.phpt
new file mode 100644
index 0000000..78c9a2c
--- /dev/null
+++ b/ext/mysqli/tests/bug54221.phpt
@@ -0,0 +1,47 @@
+--TEST--
+Bug #54221 mysqli::get_warnings segfault when used in multi queries
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--INI--
+mysqli.max_links = 1
+mysqli.allow_persistent = Off
+mysqli.max_persistent = 0
+mysqli.reconnect = Off
+--FILE--
+<?php
+ include ("connect.inc");
+
+ $link = mysqli_init();
+ if (!my_mysqli_real_connect($link, $host, $user, $passwd, $db, $port, $socket)) {
+ printf("[002] Connect failed, [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+ }
+
+ $create = "CREATE TEMPORARY TABLE IF NOT EXISTS t54221(a int)";
+
+ $query = "$create;$create;$create;";
+ if ($link->multi_query($query)) {
+ do {
+ $sth = $link->store_result();
+
+ if ($link->warning_count) {
+ $warnings = $link->get_warnings();
+ if ($warnings) {
+ do {
+ echo "Warning: ".$warnings->errno.": ".$warnings->message."\n";
+ } while ($warnings->next());
+ }
+ }
+ } while ($link->more_results() && $link->next_result());
+ }
+
+ mysqli_close($link);
+
+ print "done!";
+?>
+--EXPECTF--
+Warning: :
+Warning: 1050: Table 't54221' already exists
+done!
diff --git a/ext/mysqli/tests/bug54674.phpt b/ext/mysqli/tests/bug54674.phpt
new file mode 100644
index 0000000..efc6730
--- /dev/null
+++ b/ext/mysqli/tests/bug54674.phpt
@@ -0,0 +1,31 @@
+--TEST--
+Bug #54674 mysqlnd valid_sjis_(head|tail) is using invalid operator and range.
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--INI--
+mysqli.max_links = 1
+mysqli.allow_persistent = Off
+mysqli.max_persistent = 0
+mysqli.reconnect = Off
+--FILE--
+<?php
+ include ("connect.inc");
+
+ $link = mysqli_init();
+ if (!my_mysqli_real_connect($link, $host, $user, $passwd, $db, $port, $socket)) {
+ printf("[002] Connect failed, [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+ }
+
+ $japanese_so = pack('H4', '835c');
+ $link->set_charset('sjis');
+ var_dump($link->real_escape_string($japanese_so) === $japanese_so);
+ mysqli_close($link);
+
+ print "done!";
+?>
+--EXPECTF--
+bool(true)
+done!
diff --git a/ext/mysqli/tests/bug55283.phpt b/ext/mysqli/tests/bug55283.phpt
new file mode 100644
index 0000000..d03daae
--- /dev/null
+++ b/ext/mysqli/tests/bug55283.phpt
@@ -0,0 +1,75 @@
+--TEST--
+Bug #55283 (SSL options set by mysqli_ssl_set ignored for MySQLi persistent connections)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+require_once("connect.inc");
+
+if ($IS_MYSQLND && !extension_loaded("openssl"))
+ die("skip PHP streams lack support for SSL. mysqli is compiled to use mysqlnd which uses PHP streams in turn.");
+
+if (!($link = @my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)))
+ die(sprintf("skip Connect failed, [%d] %s", mysqli_connect_errno(), mysqli_connect_error()));
+
+$row = NULL;
+if ($res = $link->query('SHOW VARIABLES LIKE "have_ssl"')) {
+ $row = $res->fetch_row();
+} else {
+ if ($link->errno == 1064 && ($res = $link->query("SHOW VARIABLES"))) {
+ while ($row = $res->fetch_row())
+ if ($row[0] == 'have_ssl')
+ break;
+ } else {
+ die(sprintf("skip Failed to test for MySQL SSL support, [%d] %s", $link->errno, $link->error));
+ }
+}
+
+
+if (empty($row))
+ die(sprintf("skip Failed to test for MySQL SSL support, [%d] %s", $link->errno, $link->error));
+
+if (($row[1] == 'NO') || ($row[1] == 'DISABLED'))
+ die(sprintf("skip MySQL has no SSL support, [%d] %s", $link->errno, $link->error));
+
+$link->close();
+?>
+--FILE--
+<?php
+ include "connect.inc";
+ $db1 = new mysqli();
+
+
+ $flags = MYSQLI_CLIENT_SSL;
+
+ $link = mysqli_init();
+ mysqli_ssl_set($link, null, null, null, null, "RC4-MD5");
+ if (my_mysqli_real_connect($link, 'p:' . $host, $user, $passwd, $db, $port, null, $flags)) {
+ $r = $link->query("SHOW STATUS LIKE 'Ssl_cipher'");
+ var_dump($r->fetch_row());
+ }
+
+ /* non-persistent connection */
+ $link2 = mysqli_init();
+ mysqli_ssl_set($link2, null, null, null, null, "RC4-MD5");
+ if (my_mysqli_real_connect($link2, $host, $user, $passwd, $db, $port, null, $flags)) {
+ $r2 = $link2->query("SHOW STATUS LIKE 'Ssl_cipher'");
+ var_dump($r2->fetch_row());
+ }
+
+ echo "done\n";
+?>
+--EXPECTF--
+array(2) {
+ [0]=>
+ string(10) "Ssl_cipher"
+ [1]=>
+ string(7) "RC4-MD5"
+}
+array(2) {
+ [0]=>
+ string(10) "Ssl_cipher"
+ [1]=>
+ string(7) "RC4-MD5"
+}
+done \ No newline at end of file
diff --git a/ext/mysqli/tests/bug55582.phpt b/ext/mysqli/tests/bug55582.phpt
new file mode 100644
index 0000000..3933845
--- /dev/null
+++ b/ext/mysqli/tests/bug55582.phpt
@@ -0,0 +1,41 @@
+--TEST--
+Bug #55582 mysqli_num_rows() returns always 0 for unbuffered, when mysqlnd is used
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+require_once("connect.inc");
+?>
+--FILE--
+<?php
+ include "connect.inc";
+ if (!($link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))) {
+ printf("[001] Cannot connect to the server");
+ }
+
+ var_dump($link->real_query("SELECT 1"));
+ $res = $link->use_result();
+ var_dump(mysqli_num_rows($res));
+ var_dump($res->fetch_assoc());
+ var_dump(mysqli_num_rows($res));
+ var_dump($res->fetch_assoc());
+ var_dump(mysqli_num_rows($res));
+
+ $link->close();
+ echo "done\n";
+?>
+--EXPECTF--
+bool(true)
+
+Warning: mysqli_num_rows(): Function cannot be used with MYSQL_USE_RESULT in %s on line %d
+int(0)
+array(1) {
+ [1]=>
+ string(1) "1"
+}
+
+Warning: mysqli_num_rows(): Function cannot be used with MYSQL_USE_RESULT in %s on line %d
+int(0)
+NULL
+int(1)
+done
diff --git a/ext/mysqli/tests/bug55653.phpt b/ext/mysqli/tests/bug55653.phpt
new file mode 100644
index 0000000..f9cd297
--- /dev/null
+++ b/ext/mysqli/tests/bug55653.phpt
@@ -0,0 +1,36 @@
+--TEST--
+Bug #55653 PS crash with libmysql when binding same variable as param and out
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ printf("[001] Connect failed, [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+ }
+
+ $in_and_out = "a";
+
+ if (!($stmt = $link->stmt_init()))
+ printf("[002] [%d] %s\n", $link->errno, $link->error);
+
+ if (!($stmt->prepare("SELECT ?")) ||
+ !($stmt->bind_param("s", $in_and_out)) ||
+ !($stmt->execute()) ||
+ !($stmt->bind_result($in_and_out)))
+ printf("[003] [%d] %s\n", $stmt->errno, $stmt->error);
+
+ if (!$stmt->fetch())
+ printf("[004] [%d] %s\n", $stmt->errno, $stmt->error);
+
+ if ("a" !== $in_and_out)
+ printf("[005] Wrong result: '%s'\n", $in_and_out);
+
+ echo "done!";
+?>
+--EXPECT--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/bug55859.phpt b/ext/mysqli/tests/bug55859.phpt
new file mode 100644
index 0000000..ba6e990
--- /dev/null
+++ b/ext/mysqli/tests/bug55859.phpt
@@ -0,0 +1,20 @@
+--TEST--
+Bug #55859 mysqli->stat property access gives error
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ printf("[001] Connect failed, [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+ }
+ var_dump(soundex(mysqli_stat($link)) === soundex($link->stat));
+ echo "done!";
+?>
+--EXPECT--
+bool(true)
+done!
diff --git a/ext/mysqli/tests/bug62046.phpt b/ext/mysqli/tests/bug62046.phpt
new file mode 100644
index 0000000..31a7328
--- /dev/null
+++ b/ext/mysqli/tests/bug62046.phpt
@@ -0,0 +1,40 @@
+--TEST--
+Bug #62046 mysqli@mysqlnd can't iterate over stored sets after call to mysqli_stmt_reset()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ printf("[001] Connect failed, [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+ }
+ if (FALSE === ($stmt = $link->prepare('SELECT 42'))) {
+ printf("[002] Prepare failed, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+ if (FALSE === $stmt->execute()) {
+ printf("[003] Execute failed, [%d] %s\n", $stmt->errorno, $stmt->error);
+ }
+ if (FALSE === $stmt->store_result()) {
+ printf("[004] store_result failed, [%d] %s\n", $stmt->errorno, $stmt->error);
+ }
+ $one = NULL;
+ if (FALSE === $stmt->bind_result($one)) {
+ printf("[005] bind_result failed, [%d] %s\n", $stmt->errorno, $stmt->error);
+ }
+ if (FALSE === $stmt->reset()) {
+ printf("[006] bind_result failed, [%d] %s\n", $stmt->errorno, $stmt->error);
+ }
+ while ($stmt->fetch()) {
+ var_dump($one);
+ }
+ $stmt->close();
+ $link->close();
+ echo "done!";
+?>
+--EXPECT--
+int(42)
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/bug62885.phpt b/ext/mysqli/tests/bug62885.phpt
new file mode 100644
index 0000000..9fb0aa0
--- /dev/null
+++ b/ext/mysqli/tests/bug62885.phpt
@@ -0,0 +1,26 @@
+--TEST--
+Bug #62885 (mysqli_poll - Segmentation fault)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once("connect.inc");
+if (!$IS_MYSQLND) {
+ die("skip mysqlnd only test");
+}
+?>
+--FILE--
+<?php
+error_reporting(E_ALL);
+$tablica = array();
+$test1 = mysqli_poll($test2, $test3, $tablica, null);
+
+$test2 = array();
+$test2 = array();
+$test1 = mysqli_poll($test2, $test3, $tablica, null);
+echo "okey";
+?>
+--EXPECTF--
+Warning: mysqli_poll(): No stream arrays were passed in %sbug62885.php on line %d
+
+Warning: mysqli_poll(): No stream arrays were passed in %sbug62885.php on line %d
+okey
diff --git a/ext/mysqli/tests/bug63398.phpt b/ext/mysqli/tests/bug63398.phpt
new file mode 100644
index 0000000..b6e6c25
--- /dev/null
+++ b/ext/mysqli/tests/bug63398.phpt
@@ -0,0 +1,36 @@
+--TEST--
+Bug #63398 (Segfault when polling closed link)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once("connect.inc");
+if (!$IS_MYSQLND) {
+ die("skip mysqlnd only test");
+}
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+require 'connect.inc';
+$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+mysqli_close($link);
+
+$read = $error = $reject = array();
+$read[] = $error[] = $reject[] = $link;
+
+mysqli_poll($read, $error, $reject, 1);
+
+echo "okey";
+?>
+--EXPECTF--
+Warning: mysqli_poll(): [1] Couldn't fetch mysqli in %sbug63398.php on line %d
+
+Warning: mysqli_poll(): [1] Couldn't fetch mysqli in %sbug63398.php on line %d
+
+Warning: mysqli_poll(): No stream arrays were passed in %sbug63398.php on line %d
+
+Warning: mysqli_poll(): [1] Couldn't fetch mysqli in %sbug63398.php on line %d
+
+Warning: mysqli_poll(): [1] Couldn't fetch mysqli in %sbug63398.php on line %d
+okey
diff --git a/ext/mysqli/tests/bug_mysql_49406.phpt b/ext/mysqli/tests/bug_mysql_49406.phpt
new file mode 100644
index 0000000..7ed7b44
--- /dev/null
+++ b/ext/mysqli/tests/bug_mysql_49406.phpt
@@ -0,0 +1,107 @@
+--TEST--
+MySQL Bug #49406 (Binding params doesn't work when selecting a date inside a CASE-WHEN, http://bugs.mysql.com/bug.php?id=49406)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ if (!($link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)))
+ printf("[001] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ $query = "SELECT CASE WHEN 0 THEN CAST('2009-12-03' AS DATE) ELSE CAST('2009-12-03' AS DATE) END";
+
+ if (!$res = $link->query($query))
+ printf("[002] [%d] %s\n", $link->errno, $link->error);
+
+ if (!$row = $res->fetch_row())
+ printf("[003] No result, [%d] %s\n", $link->errno, $link->error);
+
+ $res->free();
+
+ if ($row[0] != '2009-12-03') {
+ printf("[004] Expecting '2009-12-03' got '%s'\n", $row[0]);
+ }
+
+ if (!$stmt = $link->prepare($query))
+ printf("[005] [%d] %s\n", $link->errno, $link->error);
+
+ if (!$stmt->execute() || !$stmt->store_result())
+ printf("[006] [%d] %s\n", $stmt->errno, $stmt->error);
+
+
+ $datatypes = array(
+ MYSQLI_TYPE_TINY => "TINY",
+ MYSQLI_TYPE_SHORT => "SHORT",
+ MYSQLI_TYPE_LONG => "LONG",
+ MYSQLI_TYPE_FLOAT => "FLOAT",
+ MYSQLI_TYPE_DOUBLE => "DOUBLE",
+ MYSQLI_TYPE_TIMESTAMP => "TIMESTAMP",
+ MYSQLI_TYPE_LONGLONG => "LONGLONG",
+ MYSQLI_TYPE_INT24 => "INT24",
+ MYSQLI_TYPE_DATE => "DATE",
+ MYSQLI_TYPE_TIME => "TIME",
+ MYSQLI_TYPE_DATETIME => "DATETIME",
+ MYSQLI_TYPE_YEAR => "YEAR",
+ MYSQLI_TYPE_ENUM => "ENUM",
+ MYSQLI_TYPE_SET => "SET",
+ MYSQLI_TYPE_TINY_BLOB => "TINYBLOB",
+ MYSQLI_TYPE_MEDIUM_BLOB => "MEDIUMBLOB",
+ MYSQLI_TYPE_LONG_BLOB => "LONGBLOB",
+ MYSQLI_TYPE_BLOB => "BLOB",
+ MYSQLI_TYPE_VAR_STRING => "VAR_STRING",
+ MYSQLI_TYPE_STRING => "STRING",
+ MYSQLI_TYPE_NULL => "NULL",
+ MYSQLI_TYPE_NEWDATE => "NEWDATE",
+ MYSQLI_TYPE_INTERVAL => "INTERVAL",
+ MYSQLI_TYPE_GEOMETRY => "GEOMETRY",
+ );
+
+ $meta_res = $stmt->result_metadata();
+ for ($field_idx = 0; $field_idx < $meta_res->field_count; $field_idx++) {
+ $field = $meta_res->fetch_field();
+ printf("Field : %d\n", $field_idx);
+ printf("Name : %s\n", $field->name);
+ printf("Orgname : %s\n", $field->orgname);
+ printf("Table : %s\n", $field->table);
+ printf("Orgtable : %s\n", $field->orgtable);
+ printf("Maxlength : %d\n", $field->max_length);
+ printf("Length : %d\n", $field->length);
+ printf("Charsetnr : %d\n", $field->charsetnr);
+ printf("Flags : %d\n", $field->flags);
+ printf("Type : %d (%s)\n", $field->type, (isset($datatypes[$field->type])) ? $datatypes[$field->type] : 'unknown');
+ printf("Decimals : %d\n", $field->decimals);
+ }
+
+ $row_stmt = null;
+ if (!$stmt->bind_result($row_stmt) || !$stmt->fetch())
+ printf("[007] [%d] %s\n", $stmt->errno, $stmt->error);
+
+ if ($row[0] != $row_stmt) {
+ printf("[008] PS and non-PS results differ, dumping data\n");
+ var_dump($row[0]);
+ var_dump($row_stmt);
+ }
+
+ $stmt->close();
+ $link->close();
+
+ echo "done";
+?>
+--EXPECTF--
+Field : %s
+Name : %s
+Orgname :%s
+Table :%s
+Orgtable :%s
+Maxlength : %d
+Length : %d
+Charsetnr : %d
+Flags : %d
+Type : %d (%s)
+Decimals : %d
+done \ No newline at end of file
diff --git a/ext/mysqli/tests/cacert.pem b/ext/mysqli/tests/cacert.pem
new file mode 100644
index 0000000..e443413
--- /dev/null
+++ b/ext/mysqli/tests/cacert.pem
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrTCCAhagAwIBAgIJAMI7xZKjhrDbMA0GCSqGSIb3DQEBBAUAMEQxCzAJBgNV
+BAYTAlNFMRAwDgYDVQQIEwdVcHBzYWxhMRAwDgYDVQQHEwdVcHBzYWxhMREwDwYD
+VQQKEwhNeVNRTCBBQjAeFw0xMDAxMjkxMTQ3MTBaFw0xNTAxMjgxMTQ3MTBaMEQx
+CzAJBgNVBAYTAlNFMRAwDgYDVQQIEwdVcHBzYWxhMRAwDgYDVQQHEwdVcHBzYWxh
+MREwDwYDVQQKEwhNeVNRTCBBQjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA
+wQYsOEfrN4ESP3FjsI8cghE+tZVuyK2gck61lwieVxjgFMtBd65mI5a1y9pmlOI1
+yM4SB2Ppqcuw7/e1CdV1y7lvHrGNt5yqEHbN4QX1gvsN8TQauP/2WILturk4R4Hq
+rKg0ZySu7f1Xhl0ed9a48LpaEHD17IcxWEGMMJwAxF0CAwEAAaOBpjCBozAMBgNV
+HRMEBTADAQH/MB0GA1UdDgQWBBSvktYQ0ahLnyxyVKqty+WpBbBrDTB0BgNVHSME
+bTBrgBSvktYQ0ahLnyxyVKqty+WpBbBrDaFIpEYwRDELMAkGA1UEBhMCU0UxEDAO
+BgNVBAgTB1VwcHNhbGExEDAOBgNVBAcTB1VwcHNhbGExETAPBgNVBAoTCE15U1FM
+IEFCggkAwjvFkqOGsNswDQYJKoZIhvcNAQEEBQADgYEAdKN1PjwMHAKG2Ww1145g
+JQGBnKxSFOUaoSvkBi/4ntTM+ysnViWh7WvxyWjR9zU9arfr7aqsDeQxm0XDOqzj
+AQ/cQIla2/Li8tXyfc06bisH/IHRaSc2zWqioTKbEwMdVOdrvq4a8V8ic3xYyIWn
+7F4WeS07J8LKardSvM0+hOA=
+-----END CERTIFICATE-----
diff --git a/ext/mysqli/tests/clean_table.inc b/ext/mysqli/tests/clean_table.inc
new file mode 100644
index 0000000..716cc84
--- /dev/null
+++ b/ext/mysqli/tests/clean_table.inc
@@ -0,0 +1,14 @@
+<?PHP
+require_once('connect.inc');
+
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ printf("[clean] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+}
+
+if (!mysqli_query($link, 'DROP TABLE IF EXISTS test')) {
+ printf("[clean] Failed to drop old test table: [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+}
+
+mysqli_close($link);
+?> \ No newline at end of file
diff --git a/ext/mysqli/tests/client-cert.pem b/ext/mysqli/tests/client-cert.pem
new file mode 100644
index 0000000..ee7f2ab
--- /dev/null
+++ b/ext/mysqli/tests/client-cert.pem
@@ -0,0 +1,46 @@
+Certificate:
+ Data:
+ Version: 1 (0x0)
+ Serial Number: 1048577 (0x100001)
+ Signature Algorithm: md5WithRSAEncryption
+ Issuer: C=SE, ST=Uppsala, L=Uppsala, O=MySQL AB
+ Validity
+ Not Before: Jan 29 11:50:22 2010 GMT
+ Not After : Jan 28 11:50:22 2015 GMT
+ Subject: C=SE, ST=Uppsala, O=MySQL AB
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (1024 bit)
+ Modulus:
+ 00:cc:9a:37:49:13:66:dc:cf:e3:0b:13:a1:23:ed:
+ 78:db:4e:bd:11:f6:8c:0d:76:f9:a3:32:56:9a:f8:
+ a1:21:6a:55:4e:4d:3f:e6:67:9d:26:99:b2:cd:a4:
+ 9a:d2:2b:59:5c:d7:8a:d3:60:68:f8:18:bd:c5:be:
+ 15:e1:2a:3c:a3:d4:61:cb:f5:11:94:17:81:81:f7:
+ 87:8c:f6:6a:d2:ee:d8:e6:77:f6:62:66:4d:2e:16:
+ 8d:08:81:4a:c9:c6:4b:31:e5:b9:c7:8a:84:96:48:
+ a7:47:8c:0d:26:90:56:4e:e6:a5:6e:8c:b3:f2:9f:
+ fc:3d:78:9b:49:6e:86:83:77
+ Exponent: 65537 (0x10001)
+ Signature Algorithm: md5WithRSAEncryption
+ 5e:1f:a3:53:5f:24:13:1c:f8:28:32:b0:7f:69:69:f3:0e:c0:
+ 34:87:10:03:7d:da:15:8b:bd:19:b8:1a:56:31:e7:85:49:81:
+ c9:7f:45:20:74:3e:89:c0:e0:26:84:51:cc:04:16:ce:69:99:
+ 01:e1:26:99:b3:e3:f5:bd:ec:5f:a0:84:e4:38:da:75:78:7b:
+ 89:9c:d2:cd:60:95:20:ba:8e:e3:7c:e6:df:76:3a:7c:89:77:
+ 02:94:86:11:3a:c4:61:7d:6f:71:83:21:8a:17:fb:17:e2:ee:
+ 02:6b:61:c1:b4:52:63:d7:d8:46:b2:c5:9c:6f:38:91:8a:35:
+ 32:0b
+-----BEGIN CERTIFICATE-----
+MIIB5zCCAVACAxAAATANBgkqhkiG9w0BAQQFADBEMQswCQYDVQQGEwJTRTEQMA4G
+A1UECBMHVXBwc2FsYTEQMA4GA1UEBxMHVXBwc2FsYTERMA8GA1UEChMITXlTUUwg
+QUIwHhcNMTAwMTI5MTE1MDIyWhcNMTUwMTI4MTE1MDIyWjAyMQswCQYDVQQGEwJT
+RTEQMA4GA1UECBMHVXBwc2FsYTERMA8GA1UEChMITXlTUUwgQUIwgZ8wDQYJKoZI
+hvcNAQEBBQADgY0AMIGJAoGBAMyaN0kTZtzP4wsToSPteNtOvRH2jA12+aMyVpr4
+oSFqVU5NP+ZnnSaZss2kmtIrWVzXitNgaPgYvcW+FeEqPKPUYcv1EZQXgYH3h4z2
+atLu2OZ39mJmTS4WjQiBSsnGSzHluceKhJZIp0eMDSaQVk7mpW6Ms/Kf/D14m0lu
+hoN3AgMBAAEwDQYJKoZIhvcNAQEEBQADgYEAXh+jU18kExz4KDKwf2lp8w7ANIcQ
+A33aFYu9GbgaVjHnhUmByX9FIHQ+icDgJoRRzAQWzmmZAeEmmbPj9b3sX6CE5Dja
+dXh7iZzSzWCVILqO43zm33Y6fIl3ApSGETrEYX1vcYMhihf7F+LuAmthwbRSY9fY
+RrLFnG84kYo1Mgs=
+-----END CERTIFICATE-----
diff --git a/ext/mysqli/tests/client-key.pem b/ext/mysqli/tests/client-key.pem
new file mode 100644
index 0000000..205b5f3
--- /dev/null
+++ b/ext/mysqli/tests/client-key.pem
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXQIBAAKBgQDMmjdJE2bcz+MLE6Ej7XjbTr0R9owNdvmjMlaa+KEhalVOTT/m
+Z50mmbLNpJrSK1lc14rTYGj4GL3FvhXhKjyj1GHL9RGUF4GB94eM9mrS7tjmd/Zi
+Zk0uFo0IgUrJxksx5bnHioSWSKdHjA0mkFZO5qVujLPyn/w9eJtJboaDdwIDAQAB
+AoGASqk/4We2En+93y3jkIO4pXafIe3w/3zZ7caRue1ehx4RUQh5d+95djuB9u7J
+HEZ7TpjM7QNyao5EueL6gvbxt0LXFvqAMni7yM9tt/HUYtHHPqYiRtUny9bKYFTm
+l8szCCMal/wD9GZU9ByHDNHm7tHUMyMhARNTYSgx+SERFmECQQD/6jJocC4SXf6f
+T3LqimWR02lbJ7qCoDgRglsUXh0zjrG+IIiAyE+QOCCx1GMe3Uw6bsIuYwdHT6as
+WcdPs04xAkEAzKulvEvLVvN5zfa/DTYRTV7jh6aDleOxjsD5oN/oJXoACnPzVuUL
+qQQMNtuAXm6Q1QItrRxpQsSKbY0UQka6JwJBAOSgoNoG5lIIYTKIMvzwGV+XBLeo
+HYsXgh+6Wo4uql3mLErUG78ZtWL9kc/tE4R+ZdyKGLaCR/1gXmH5bwN4B/ECQEBb
+uUH8k3REG4kojesZlVc+/00ojzgS4UKCa/yqa9VdB6ZBz8MDQydinnShkTwgiGpy
+xOoqhO753o2UT0qH8wECQQC99IEJWUnwvExVMkLaZH5NjAFJkb22sjkmuT11tAgU
+RQgOMoDOm6driojnOnDWOkx1r1Gy9NgMLooduja4v6cx
+-----END RSA PRIVATE KEY-----
diff --git a/ext/mysqli/tests/connect.inc b/ext/mysqli/tests/connect.inc
new file mode 100644
index 0000000..3a9d8ec
--- /dev/null
+++ b/ext/mysqli/tests/connect.inc
@@ -0,0 +1,273 @@
+<?php
+ /*
+ Default values are "localhost", "root",
+ database "stest" and empty password.
+ Change the MYSQL_TEST environment values
+ if you want to use another configuration
+ */
+
+ $driver = new mysqli_driver;
+
+ $host = getenv("MYSQL_TEST_HOST") ? getenv("MYSQL_TEST_HOST") : "localhost";
+ $port = getenv("MYSQL_TEST_PORT") ? getenv("MYSQL_TEST_PORT") : 3306;
+ $user = getenv("MYSQL_TEST_USER") ? getenv("MYSQL_TEST_USER") : "root";
+ $passwd = getenv("MYSQL_TEST_PASSWD") ? getenv("MYSQL_TEST_PASSWD") : "";
+ $db = getenv("MYSQL_TEST_DB") ? getenv("MYSQL_TEST_DB") : "test";
+ $engine = getenv("MYSQL_TEST_ENGINE") ? getenv("MYSQL_TEST_ENGINE") : "MyISAM";
+ $socket = getenv("MYSQL_TEST_SOCKET") ? getenv("MYSQL_TEST_SOCKET") : null;
+ $skip_on_connect_failure = getenv("MYSQL_TEST_SKIP_CONNECT_FAILURE") ? getenv("MYSQL_TEST_SKIP_CONNECT_FAILURE") : true;
+ $connect_flags = getenv("MYSQL_TEST_CONNECT_FLAGS") ? (int)getenv("MYSQL_TEST_CONNECT_FLAGS") : 0;
+ if ($socket) {
+ ini_set('mysqli.default_socket', $socket);
+ }
+
+ /* Development setting: test experimal features and/or feature requests that never worked before? */
+ $TEST_EXPERIMENTAL = (in_array(getenv("MYSQL_TEST_EXPERIMENTAL"), array(0, 1))) ?
+ ((1 == getenv("MYSQL_TEST_EXPERIMENTAL")) ? true : false) :
+ false;
+
+ $IS_MYSQLND = stristr(mysqli_get_client_info(), "mysqlnd");
+ if (!$IS_MYSQLND) {
+ $MYSQLND_VERSION = NULL;
+ } else {
+ /*
+ The formatting of the version reported by mysqli_get_client_info()
+ has changed significantly in the past. To get tests working properly
+ with PHP 5.3.0 and up, we set everything that looks like prior to
+ PHP 5.3.0 to version 5.0.4 = 5 * 10000 + 0 * 100 + 4 = 50004.
+ PHP 5.3.0 reports mysqlnd 5.0.5 dev (= 5 * 10000 + 0 * 100 + 5 = 50005.
+ */
+ if (preg_match('@Revision:\s+(\d+)\s*\$@ism', mysqli_get_client_info(), $matches)) {
+ /* something prior to PHP 5.3.0 */
+ $MYSQLND_VERSION = 50004;
+ } else if (preg_match('@^mysqlnd (\d+)\.(\d+)\.(\d+).*@ism', mysqli_get_client_info(), $matches)) {
+ /* formatting schema used by PHP 5.3.0 */
+ $MYSQLND_VERSION = (int)$matches[1] * 10000 + (int)$matches[2] * 100 + (int)$matches[3];
+ } else if (preg_match('@^mysqlnd/PHP 6.0.0-dev@ism', mysqli_get_client_info(), $matches)) {
+ /*
+ PHP 6.0 at the time of the first PHP 5.3.0 release.
+ HEAD and 5.3 have been in sync when 5.3.0 was released.
+ It is at least 5.0.5-dev.
+ */
+ $MYSQLND_VERSION = 50005;
+ } else {
+ /* unknown */
+ $MYSQLND_VERSION = -1;
+ }
+
+ }
+
+ if (!function_exists('sys_get_temp_dir')) {
+ function sys_get_temp_dir() {
+
+ if (!empty($_ENV['TMP']))
+ return realpath( $_ENV['TMP'] );
+ if (!empty($_ENV['TMPDIR']))
+ return realpath( $_ENV['TMPDIR'] );
+ if (!empty($_ENV['TEMP']))
+ return realpath( $_ENV['TEMP'] );
+
+ $temp_file = tempnam(md5(uniqid(rand(), TRUE)), '');
+ if ($temp_file) {
+ $temp_dir = realpath(dirname($temp_file));
+ unlink($temp_file);
+ return $temp_dir;
+ }
+ return FALSE;
+ }
+ }
+
+ if (!function_exists('my_mysqli_connect')) {
+
+ /**
+ * Whenever possible, please use this wrapper to make testing ot MYSQLI_CLIENT_COMPRESS (and potentially SSL) possible
+ *
+ * @param enable_env_flags Enable setting of connection flags through env(MYSQL_TEST_CONNECT_FLAGS)?
+ */
+ function my_mysqli_connect($host, $user, $passwd, $db, $port, $socket, $enable_env_flags = true) {
+ global $connect_flags;
+
+ $flags = ($enable_env_flags) ? $connect_flags : false;
+
+ if ($flags !== false) {
+ $link = mysqli_init();
+ if (!mysqli_real_connect($link, $host, $user, $passwd, $db, $port, $socket, $flags))
+ $link = false;
+ } else {
+ $link = mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+ }
+
+ return $link;
+ }
+
+ /**
+ * Whenever possible, please use this wrapper to make testing ot MYSQLI_CLIENT_COMPRESS (and potentially SSL) possible
+ *
+ * @param enable_env_flags Enable setting of connection flags through env(MYSQL_TEST_CONNECT_FLAGS)
+ */
+ function my_mysqli_real_connect($link, $host, $user, $passwd, $db, $port, $socket, $flags = 0, $enable_env_flags = true) {
+ global $connect_flags;
+
+ if ($enable_env_flags)
+ $flags & $connect_flags;
+
+ return mysqli_real_connect($link, $host, $user, $passwd, $db, $port, $socket, $flags);
+ }
+
+ class my_mysqli extends mysqli {
+ public function __construct($host, $user, $passwd, $db, $port, $socket, $enable_env_flags = true) {
+ global $connect_flags;
+
+ $flags = ($enable_env_flags) ? $connect_flags : false;
+
+ if ($flags !== false) {
+ parent::init();
+ $this->real_connect($host, $user, $passwd, $db, $port, $socket, $flags);
+ } else {
+ parent::__construct($host, $user, $passwd, $db, $port, $socket);
+ }
+ }
+ }
+
+ function my_get_charsets($link) {
+
+ /* Those tree are set by SET NAMES */
+ $charsets = array(
+ 'client' => NULL,
+ 'results' => NULL,
+ 'connection' => NULL,
+ );
+
+ if (!($res = mysqli_query($link, "SHOW VARIABLES LIKE '%character%'"))) {
+ printf("[%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ return $charsets;
+ }
+
+ $names = array();
+ while ($row = mysqli_fetch_assoc($res)) {
+ $names[$row['Variable_name']] = $row['Value'];
+ }
+ mysqli_free_result($res);
+
+ if (!($res = mysqli_query($link, sprintf("SHOW CHARACTER SET LIKE '%s'", $names['character_set_client']))) ||
+ !($details = mysqli_fetch_assoc($res))) {
+ printf("[%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ return $charsets;
+ }
+ mysqli_free_result($res);
+
+ $charsets['client'] = array(
+ 'charset' => $details['Charset'],
+ 'desc' => $details['Description'],
+ 'collation' => $details['Default collation'],
+ 'maxlen' => $details['Maxlen'],
+ 'nr' => NULL,
+ );
+
+ if (!($res = mysqli_query($link, sprintf("SHOW COLLATION LIKE '%s'", $details['Default collation']))) ||
+ !($collation = mysqli_fetch_assoc($res))) {
+ printf("[%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ return $charsets;
+ }
+ mysqli_free_result($res);
+ $charsets['client']['nr'] = $collation['Id'];
+
+ if (!($res = mysqli_query($link, sprintf("SHOW CHARACTER SET LIKE '%s'", $names['character_set_results']))) ||
+ !($details = mysqli_fetch_assoc($res))) {
+ printf("[%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ return $charsets;
+ }
+ mysqli_free_result($res);
+
+ $charsets['results'] = array(
+ 'charset' => $details['Charset'],
+ 'desc' => $details['Description'],
+ 'collation' => $details['Default collation'],
+ 'maxlen' => $details['Maxlen'],
+ 'nr' => NULL,
+ );
+
+ if (!($res = mysqli_query($link, sprintf("SHOW COLLATION LIKE '%s'", $details['Default collation']))) ||
+ !($collation = mysqli_fetch_assoc($res))) {
+ printf("[%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ return $charsets;
+ }
+ mysqli_free_result($res);
+ $charsets['results']['nr'] = $collation['Id'];
+
+
+ if (!($res = mysqli_query($link, sprintf("SHOW CHARACTER SET LIKE '%s'", $names['character_set_connection']))) ||
+ !($details = mysqli_fetch_assoc($res))) {
+ printf("[%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ return $charsets;
+ }
+ mysqli_free_result($res);
+
+ $charsets['connection'] = array(
+ 'charset' => $details['Charset'],
+ 'desc' => $details['Description'],
+ 'collation' => $details['Default collation'],
+ 'maxlen' => $details['Maxlen'],
+ 'nr' => NULL,
+ );
+
+ if (!($res = mysqli_query($link, sprintf("SHOW COLLATION LIKE '%s'", $details['Default collation']))) ||
+ !($collation = mysqli_fetch_assoc($res))) {
+ printf("[%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ return $charsets;
+ }
+ mysqli_free_result($res);
+ $charsets['connection']['nr'] = $collation['Id'];
+
+ return $charsets;
+ }
+
+ function have_innodb($link) {
+ if (($res = $link->query("SHOW VARIABLES LIKE 'have_innodb'")) &&
+ ($row = $res->fetch_row()) &&
+ !empty($row)) {
+ if ($row[1] == "DISABLED" || $row[1] == "NO") {
+ return false;
+ }
+ return true;
+ } else {
+ /* MySQL 5.6.1+ */
+ if ($res = $link->query("SHOW ENGINES")) {
+ while ($row = $res->fetch_assoc()) {
+ if (!isset($row['Engine']) || !isset($row['Support']))
+ return false;
+
+ if (('InnoDB' == $row['Engine']) &&
+ (('YES' == $row['Support']) || ('DEFAULT' == $row['Support']))
+ ) {
+ return true;
+ }
+ }
+ return false;
+ } else {
+ return false;
+ }
+ }
+ return false;
+ }
+
+ } else {
+ printf("skip Eeeek/BUG/FIXME - connect.inc included twice! skipif bug?\n");
+ }
+
+ function handle_catchable_fatal($errno, $error, $file, $line) {
+ static $errcodes = array();
+ if (empty($errcodes)) {
+ $constants = get_defined_constants();
+ foreach ($constants as $name => $value) {
+ if (substr($name, 0, 2) == "E_")
+ $errcodes[$value] = $name;
+ }
+ }
+ printf("[%s] %s in %s on line %s\n",
+ (isset($errcodes[$errno])) ? $errcodes[$errno] : $errno,
+ $error, $file, $line);
+
+ return true;
+ }
+?>
diff --git a/ext/mysqli/tests/local_infile_tools.inc b/ext/mysqli/tests/local_infile_tools.inc
new file mode 100644
index 0000000..bb9872f
--- /dev/null
+++ b/ext/mysqli/tests/local_infile_tools.inc
@@ -0,0 +1,156 @@
+<?php
+ /* Utility function for mysqli_set_local_infile*.phpt tests */
+ function shutdown_clean($file) {
+ if ($file) {
+ unlink($file);
+ }
+ }
+
+ function check_local_infile_support($link, $engine, $table_name = 'test') {
+
+ if (!$res = mysqli_query($link, 'SHOW VARIABLES LIKE "local_infile"'))
+ return "Cannot check if Server variable 'local_infile' is set to 'ON'";
+
+ $row = mysqli_fetch_assoc($res);
+ mysqli_free_result($res);
+ if ('ON' != $row['Value'])
+ return sprintf("Server variable 'local_infile' seems not set to 'ON', found '%s'", $row['Value']);
+
+ if (!mysqli_query($link, sprintf('DROP TABLE IF EXISTS %s', $table_name))) {
+ return "Failed to drop old test table";
+ }
+
+ if (!mysqli_query($link, $sql = sprintf('CREATE TABLE %s(id INT, label CHAR(1), PRIMARY KEY(id)) ENGINE=%s',
+ $table_name, $engine)))
+ return "Failed to create test table: $sql";
+
+ $file = create_standard_csv(1, false);
+ if (!$file) {
+ mysqli_query($link, sprintf('DROP TABLE IF EXISTS %s', $table_name));
+ return "Cannot create CSV file";
+ }
+
+ if (!@mysqli_query($link, sprintf("LOAD DATA LOCAL INFILE '%s'
+ INTO TABLE %s
+ FIELDS TERMINATED BY ';' OPTIONALLY ENCLOSED BY '\''
+ LINES TERMINATED BY '\n'",
+ mysqli_real_escape_string($link, $file),
+ $table_name))) {
+ if (1148 == mysqli_errno($link)) {
+ mysqli_query($link, sprintf('DROP TABLE IF EXISTS %s', $table_name));
+ return "Cannot test LOAD DATA LOCAL INFILE, [1148] The used command is not allowed with this MySQL version";
+ } else if ($link->errno) {
+ return $link->error;
+ }
+ }
+ mysqli_query($link, sprintf('DROP TABLE IF EXISTS %s', $table_name));
+ return "";
+ }
+
+ function create_standard_csv($offset, $verbose = true) {
+ // create a CVS file
+ $file = tempnam(sys_get_temp_dir(), 'mysqli_test');
+ if (!$fp = fopen($file, 'w')) {
+ if ($verbose)
+ printf("[%03d + 1] Cannot create CVS file '%s'\n", $offset, $file);
+ return NULL;
+ } else {
+ /* Looks ugly? No, handy if you have crashes... */
+ register_shutdown_function("shutdown_clean", $file);
+ }
+
+ if ((version_compare(PHP_VERSION, '5.9.9', '>') == 1)) {
+ if (!fwrite($fp, (binary)"'97';'x';\n") ||
+ !fwrite($fp, (binary)"'98';'y';\n") ||
+ !fwrite($fp, (binary)"99;'z';\n")) {
+ if ($verbose)
+ printf("[%03d + 2] Cannot write CVS file '%s'\n", $offset, $file);
+ return NULL;
+ }
+ } else {
+ if (!fwrite($fp, "97;'x';\n") ||
+ !fwrite($fp, "98;'y';\n") ||
+ !fwrite($fp, "99;'z';\n")) {
+ if ($verbose)
+ printf("[%03d + 3] Cannot write CVS file '%s'\n", $offset, $file);
+ return NULL;
+ }
+ }
+
+ fclose($fp);
+
+ if (!chmod($file, 0644)) {
+ if ($verbose)
+ printf("[%03d + 4] Cannot change the file perms of '%s' from 0600 to 0644, MySQL might not be able to read it\n",
+ $offset, $file);
+ return NULL;
+ }
+ return $file;
+ }
+
+ function try_handler($offset, $link, $file, $handler, $expected = null) {
+
+ if ('default' == $handler) {
+ mysqli_set_local_infile_default($link);
+ } else if (!mysqli_set_local_infile_handler($link, $handler)) {
+ printf("[%03d] Cannot set infile handler to '%s'\n", $offset, $handler);
+ return false;
+ }
+ printf("Callback set to '%s'\n", $handler);
+
+ if (!mysqli_query($link, sprintf("DELETE FROM test"))) {
+ printf("[%03d] Cannot remove records, [%d] %s\n", $offset + 1, mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ if (!@mysqli_query($link, sprintf("LOAD DATA LOCAL INFILE '%s'
+ INTO TABLE test
+ FIELDS TERMINATED BY ';' OPTIONALLY ENCLOSED BY '\''
+ LINES TERMINATED BY '\n'",
+ mysqli_real_escape_string($link, $file)))) {
+ printf("[%03d] LOAD DATA failed, [%d] %s\n",
+ $offset + 2,
+ mysqli_errno($link), mysqli_error($link));
+ }
+
+ if (!$res = mysqli_query($link, "SELECT id, label FROM test ORDER BY id")) {
+ printf("[%03d] [%d] %s\n", $offset + 3, mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ if (!is_array($expected))
+ return true;
+
+ foreach ($expected as $k => $values) {
+ if (!$tmp = mysqli_fetch_assoc($res)) {
+ printf("[%03d/%d] [%d] '%s'\n", $offset + 4, $k, mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+ if ($values['id'] != $tmp['id']) {
+ printf("[%03d/%d] Expecting %s got %s\n",
+ $offset + 5, $k,
+ $values['id'], $tmp['id']);
+ return false;
+ }
+ if ($values['label'] != $tmp['label']) {
+ printf("[%03d/%d] Expecting %s got %s\n",
+ $offset + 6, $k,
+ $values['label'], $tmp['label']);
+ return false;
+ }
+ }
+
+ if ($res && $tmp = mysqli_fetch_assoc($res)) {
+ printf("[%03d] More results than expected!\n", $offset + 7);
+ do {
+ var_dump($tmp);
+ } while ($tmp = mysqli_fetch_assoc($res));
+ return false;
+ }
+
+ if ($res)
+ mysqli_free_result($res);
+
+ return true;
+ }
+?> \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_affected_rows.phpt b/ext/mysqli/tests/mysqli_affected_rows.phpt
new file mode 100644
index 0000000..958b83c
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_affected_rows.phpt
@@ -0,0 +1,135 @@
+--TEST--
+mysqli_affected_rows()
+--SKIPIF--
+<?php
+ require_once('skipif.inc');
+ require_once('skipifemb.inc');
+ require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_affected_rows()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_affected_rows($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_affected_rows($link, $link)))
+ printf("[003] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[004] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ if (0 !== ($tmp = mysqli_affected_rows($link)))
+ printf("[005] Expecting int/0, got %s/%s. [%d] %s\n",
+ gettype($tmp), $tmp, mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, 'DROP TABLE IF EXISTS test'))
+ printf("[006] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, 'CREATE TABLE test(id INT, label CHAR(1), PRIMARY KEY(id)) ENGINE = ' . $engine))
+ printf("[007] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, "INSERT INTO test(id, label) VALUES (1, 'a')"))
+ printf("[008] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (1 !== ($tmp = mysqli_affected_rows($link)))
+ printf("[010] Expecting int/1, got %s/%s\n", gettype($tmp), $tmp);
+
+ // ignore INSERT error, NOTE: command line returns 0, affected_rows returns -1 as documented
+ mysqli_query($link, "INSERT INTO test(id, label) VALUES (1, 'a')");
+ if (-1 !== ($tmp = mysqli_affected_rows($link)))
+ printf("[011] Expecting int/-1, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_query($link, "INSERT INTO test(id, label) VALUES (1, 'a') ON DUPLICATE KEY UPDATE id = 4"))
+ printf("[012] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (2 !== ($tmp = mysqli_affected_rows($link)))
+ printf("[013] Expecting int/2, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_query($link, "INSERT INTO test(id, label) VALUES (2, 'b'), (3, 'c')"))
+ printf("[014] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (2 !== ($tmp = mysqli_affected_rows($link)))
+ printf("[015] Expecting int/2, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_query($link, "INSERT IGNORE INTO test(id, label) VALUES (1, 'a')")) {
+ printf("[016] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ if (1 !== ($tmp = mysqli_affected_rows($link)))
+ printf("[017] Expecting int/1, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_query($link, "INSERT INTO test(id, label) SELECT id + 10, label FROM test"))
+ printf("[018] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (4 !== ($tmp = mysqli_affected_rows($link)))
+ printf("[019] Expecting int/4, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_query($link, "REPLACE INTO test(id, label) values (4, 'd')"))
+ printf("[020] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (2 !== ($tmp = mysqli_affected_rows($link)))
+ printf("[021] Expecting int/2, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_query($link, "REPLACE INTO test(id, label) values (5, 'e')"))
+ printf("[022] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (1 !== ($tmp = mysqli_affected_rows($link)))
+ printf("[023] Expecting int/1, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_query($link, "UPDATE test SET label = 'a' WHERE id = 2"))
+ printf("[024] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (1 !== ($tmp = mysqli_affected_rows($link)))
+ printf("[025] Expecting int/1, got %s/%s\n", gettype($tmp), $tmp);
+
+ $charsets = array('utf8');
+ foreach ($charsets as $k => $charset) {
+ if (!($res = mysqli_query($link, sprintf("SHOW CHARACTER SET LIKE '%s'", $charset))))
+ continue;
+ mysqli_free_result($res);
+ if (true !== ($tmp = mysqli_set_charset($link, $charset)))
+ printf("[026] Expecting boolean/true got %s/%s\n",
+ gettype($tmp), $tmp);
+ if (0 !== ($tmp = mysqli_affected_rows($link)))
+ printf("[027] Expecting int/0 got %s/%s\n", gettype($tmp), $tmp);
+ }
+
+ if (!mysqli_query($link, "UPDATE test SET label = 'a' WHERE id = 2")) {
+ printf("[028] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ if (0 !== ($tmp = mysqli_affected_rows($link)))
+ printf("[029] Expecting int/0, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_query($link, "UPDATE test SET label = 'a' WHERE id = 100")) {
+ printf("[030] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ if (0 !== ($tmp = mysqli_affected_rows($link)))
+ printf("[031] Expecting int/0, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_query($link, 'DROP TABLE IF EXISTS test'))
+ printf("[032] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+
+ mysqli_close($link);
+
+ if (NULL !== ($tmp = @mysqli_affected_rows($link)))
+ printf("[033] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_affected_rows_oo.phpt b/ext/mysqli/tests/mysqli_affected_rows_oo.phpt
new file mode 100644
index 0000000..6da026b
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_affected_rows_oo.phpt
@@ -0,0 +1,114 @@
+--TEST--
+mysqli->affected_rows
+--SKIPIF--
+<?php
+ require_once('skipif.inc');
+ require_once('skipifemb.inc');
+ require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $mysqli = new mysqli();
+ if (NULL !== ($tmp = @$mysqli->affected_rows))
+ printf("[000a] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$mysqli = new my_mysqli($host, $user, $passwd, $db, $port, $socket)) {
+ printf("[001] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+ }
+
+ if (0 !== ($tmp = $mysqli->affected_rows))
+ printf("[002] Expecting int/0, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$mysqli->query('DROP TABLE IF EXISTS test'))
+ printf("[003] [%d] %s\n", $mysqli->errno, $mysqli->error);
+
+ if (!$mysqli->query('CREATE TABLE test(id INT, label CHAR(1), PRIMARY KEY(id)) ENGINE = ' . $engine))
+ printf("[004] [%d] %s\n", $mysqli->errno, $mysqli->error);
+
+ if (!$mysqli->query("INSERT INTO test(id, label) VALUES (1, 'a')"))
+ printf("[005] [%d] %s\n", $mysqli->errno, $mysqli->error);
+
+ if (1 !== ($tmp = $mysqli->affected_rows))
+ printf("[006] Expecting int/1, got %s/%s\n", gettype($tmp), $tmp);
+
+ // ignore INSERT error, NOTE: command line returns 0, affected_rows returns -1 as documented
+ $mysqli->query("INSERT INTO test(id, label) VALUES (1, 'a')");
+ if (-1 !== ($tmp = $mysqli->affected_rows))
+ printf("[007] Expecting int/-1, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$mysqli->query("INSERT INTO test(id, label) VALUES (1, 'a') ON DUPLICATE KEY UPDATE id = 4"))
+ printf("[008] [%d] %s\n", $mysqli->errno, $mysqli->error);
+
+ if (2 !== ($tmp = $mysqli->affected_rows))
+ printf("[009] Expecting int/2, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$mysqli->query("INSERT INTO test(id, label) VALUES (2, 'b'), (3, 'c')"))
+ printf("[010] [%d] %s\n", $mysqli->errno, $mysqli->error);
+
+ if (2 !== ($tmp = $mysqli->affected_rows))
+ printf("[011] Expecting int/2, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$mysqli->query("INSERT IGNORE INTO test(id, label) VALUES (1, 'a')")) {
+ printf("[012] [%d] %s\n", $mysqli->errno, $mysqli->error);
+ }
+
+ if (1 !== ($tmp = $mysqli->affected_rows))
+ printf("[013] Expecting int/1, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$mysqli->query("INSERT INTO test(id, label) SELECT id + 10, label FROM test"))
+ printf("[014] [%d] %s\n", $mysqli->errno, $mysqli->error);
+
+ if (4 !== ($tmp = $mysqli->affected_rows))
+ printf("[015] Expecting int/4, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$mysqli->query("REPLACE INTO test(id, label) values (4, 'd')"))
+ printf("[015] [%d] %s\n", $mysqli->errno, $mysqli->error);
+
+ if (2 !== ($tmp = $mysqli->affected_rows))
+ printf("[016] Expecting int/2, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$mysqli->query("REPLACE INTO test(id, label) values (5, 'e')"))
+ printf("[017] [%d] %s\n", $mysqli->errno, $mysqli->error);
+
+ if (1 !== ($tmp = $mysqli->affected_rows))
+ printf("[018] Expecting int/1, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$mysqli->query("UPDATE test SET label = 'a' WHERE id = 2"))
+ printf("[019] [%d] %s\n", $mysqli->errno, $mysqli->error);
+
+ if (1 !== ($tmp = $mysqli->affected_rows))
+ printf("[020] Expecting int/1, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$mysqli->query("UPDATE test SET label = 'a' WHERE id = 2")) {
+ printf("[021] [%d] %s\n", $mysqli->errno, $mysqli->error);
+ }
+
+ if (0 !== ($tmp = $mysqli->affected_rows))
+ printf("[022] Expecting int/0, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$mysqli->query("UPDATE test SET label = 'a' WHERE id = 100")) {
+ printf("[023] [%d] %s\n", $mysqli->errno, $mysqli->error);
+ }
+
+ if (0 !== ($tmp = $mysqli->affected_rows))
+ printf("[024] Expecting int/0, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$mysqli->query('DROP TABLE IF EXISTS test'))
+ printf("[025] [%d] %s\n", $mysqli->errno, $mysqli->error);
+
+ $mysqli->close();
+
+ if (NULL !== ($tmp = @$mysqli->affected_rows))
+ printf("[026] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_auth_pam.phpt b/ext/mysqli/tests/mysqli_auth_pam.phpt
new file mode 100644
index 0000000..fe15529
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_auth_pam.phpt
@@ -0,0 +1,98 @@
+--TEST--
+PAM auth plugin
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('connect.inc');
+
+if (version_compare(PHP_VERSION, '5.3.99') >= 0) {
+ die("SKIP Available as of PHP 5.3.99");
+}
+
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ die(sprintf("SKIP Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket));
+}
+
+if ($link->server_version < 50500)
+ die(sprintf("SKIP Needs MySQL 5.5 or newer, found MySQL %s\n", $link->server_info));
+
+if (!$res = $link->query("SHOW PLUGINS"))
+ die(sprintf("SKIP [%d] %s\n", $link->errno, $link->error));
+
+$have_pam = false;
+while ($row = $res->fetch_assoc()) {
+ if (isset($row['Name']) && ('mysql_clear_password' == $row['Name'])) {
+ $have_pam = true;
+ break;
+ }
+}
+$res->close();
+
+if (!$have_pam)
+ die("SKIP Server PAM plugin not installed");
+
+
+mysqli_query($link, 'DROP USER pamtest');
+mysqli_query($link, 'DROP USER pamtest@localhost');
+
+if (!mysqli_query($link, 'CREATE USER pamtest@"%" IDENTIFIED WITH mysql_clear_password') ||
+ !mysqli_query($link, 'CREATE USER pamtest@"localhost" IDENTIFIED WITH mysql_clear_password')) {
+ printf("skip Cannot create second DB user [%d] %s", mysqli_errno($link), mysqli_error($link));
+ mysqli_close($link);
+ die("skip CREATE USER failed");
+}
+
+if (!$link->query("CREATE TABLE test (id INT)") || !$link->query("INSERT INTO test(id) VALUES (1)"))
+ die(sprintf("SKIP [%d] %s\n", $link->errno, $link->error));
+
+
+
+if (!mysqli_query($link, sprintf("GRANT SELECT ON TABLE %s.test TO pamtest@'%%'", $db)) ||
+ !mysqli_query($link, sprintf("GRANT SELECT ON TABLE %s.test TO pamtest@'localhost'", $db))) {
+ printf("skip Cannot grant SELECT to user [%d] %s", mysqli_errno($link), mysqli_error($link));
+ mysqli_close($link);
+ die("skip GRANT failed");
+}
+?>
+--INI--
+max_execution_time=240
+--FILE--
+<?php
+ require_once('connect.inc');
+ require_once('table.inc');
+
+ if (!$link = my_mysqli_connect($host, 'pamtest', 'pamtest', $db, $port, $socket)) {
+ printf("[001] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+ } else {
+
+ if (!$res = $link->query("SELECT id FROM test WHERE id = 1"))
+ printf("[002] [%d] %s\n", $link->errno, $link->error);
+
+ if (!$row = mysqli_fetch_assoc($res)) {
+ printf("[003] [%d] %s\n", $link->errno, $link->error);
+ }
+
+ if ($row['id'] != 1) {
+ printf("[004] Expecting 1 got %s/'%s'", gettype($row['id']), $row['id']);
+ }
+
+ $res->close();
+ $link->close();
+ }
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+ mysqli_query($link, 'DROP USER pamtest');
+ mysqli_query($link, 'DROP USER pamtest@localhost');
+?>
+--EXPECTF--
+
+Warning: mysqli_real_connect(): (28000/1045): Access denied for user %s
+[001] Cannot connect to the server using host=%s
+done!
diff --git a/ext/mysqli/tests/mysqli_autocommit.phpt b/ext/mysqli/tests/mysqli_autocommit.phpt
new file mode 100644
index 0000000..a93d89f
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_autocommit.phpt
@@ -0,0 +1,147 @@
+--TEST--
+mysqli_autocommit()
+--SKIPIF--
+<?php
+ require_once('skipif.inc');
+ require_once('skipifemb.inc');
+ require_once('connect.inc');
+ require_once('skipifconnectfailure.inc');
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ die(sprintf("skip Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket));
+ }
+
+ if (!have_innodb($link))
+ die(sprintf("Needs InnoDB support, [%d] %s", $link->errno, $link->error));
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_autocommit()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_autocommit($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_autocommit($link, $link, $link)))
+ printf("[003] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ printf("[004] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+ }
+
+ if (!is_bool($tmp = mysqli_autocommit($link, true)))
+ printf("[005] Expecting boolean/any, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_query($link, 'SET AUTOCOMMIT = 0'))
+ printf("[006] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$res = mysqli_query($link, 'SELECT @@autocommit as auto_commit'))
+ printf("[007] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $tmp = mysqli_fetch_assoc($res);
+ mysqli_free_result($res);
+ if ($tmp['auto_commit'])
+ printf("[008] Cannot turn off autocommit\n");
+
+ if (true !== ($tmp = mysqli_autocommit($link, true)))
+ printf("[009] Expecting true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$res = mysqli_query($link, 'SELECT @@autocommit as auto_commit'))
+ printf("[010] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ $tmp = mysqli_fetch_assoc($res);
+ mysqli_free_result($res);
+ if (!$tmp['auto_commit'])
+ printf("[011] Cannot turn on autocommit\n");
+
+ if (!mysqli_query($link, 'DROP TABLE IF EXISTS test'))
+ printf("[012] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, 'CREATE TABLE test(id INT) ENGINE = InnoDB')) {
+ printf("[013] Cannot create test table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ if (!mysqli_query($link, 'INSERT INTO test(id) VALUES (1)'))
+ printf("[014] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, 'ROLLBACK'))
+ printf("[015] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$res = mysqli_query($link, 'SELECT COUNT(*) AS num FROM test'))
+ printf("[016] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if ((!$tmp = mysqli_fetch_assoc($res)) || (1 != $tmp['num']))
+ printf("[17] Expecting 1 row in table test, found %d rows. [%d] %s\n",
+ $tmp['num'], mysqli_errno($link), mysqli_error($link));
+
+ mysqli_free_result($res);
+
+ if (!mysqli_query($link, 'DROP TABLE IF EXISTS test'))
+ printf("[018] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, 'SET AUTOCOMMIT = 1'))
+ printf("[019] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$res = mysqli_query($link, 'SELECT @@autocommit as auto_commit'))
+ printf("[020] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ $tmp = mysqli_fetch_assoc($res);
+ mysqli_free_result($res);
+ if (!$tmp['auto_commit'])
+ printf("[021] Cannot turn on autocommit\n");
+
+ if (true !== ($tmp = mysqli_autocommit($link, false)))
+ printf("[022] Expecting true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_query($link, 'CREATE TABLE test(id INT) ENGINE = InnoDB')) {
+ printf("[023] Cannot create test table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ if (!mysqli_query($link, 'INSERT INTO test(id) VALUES (1)'))
+ printf("[024] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, 'ROLLBACK'))
+ printf("[025] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$res = mysqli_query($link, 'SELECT COUNT(*) AS num FROM test'))
+ printf("[026] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ $tmp = mysqli_fetch_assoc($res);
+ if (0 != $tmp['num'])
+ printf("[27] Expecting 0 rows in table test, found %d rows\n", $tmp['num']);
+ mysqli_free_result($res);
+
+ if (!mysqli_query($link, 'INSERT INTO test(id) VALUES (1)'))
+ printf("[028] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, 'COMMIT'))
+ printf("[029] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$res = mysqli_query($link, 'SELECT COUNT(*) AS num FROM test'))
+ printf("[030] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if ((!$tmp = mysqli_fetch_assoc($res)) || (1 != $tmp['num']))
+ printf("[31] Expecting 1 row in table test, found %d rows. [%d] %s\n",
+ $tmp['num'], mysqli_errno($link), mysqli_error($link));
+ mysqli_free_result($res);
+
+ if (!mysqli_query($link, 'DROP TABLE IF EXISTS test'))
+ printf("[032] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ mysqli_close($link);
+
+ if (NULL !== ($tmp = @mysqli_autocommit($link, false)))
+ printf("[033] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+done!
diff --git a/ext/mysqli/tests/mysqli_autocommit_oo.phpt b/ext/mysqli/tests/mysqli_autocommit_oo.phpt
new file mode 100644
index 0000000..3a5a257
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_autocommit_oo.phpt
@@ -0,0 +1,137 @@
+--TEST--
+mysqli->autocommit()
+--SKIPIF--
+<?php
+ require_once('skipif.inc');
+ require_once('skipifemb.inc');
+ require_once('skipifconnectfailure.inc');
+ require_once('connect.inc');
+
+ if (!$link = new my_mysqli($host, $user, $passwd, $db, $port, $socket)) {
+ printf("skip Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+ exit(1);
+ }
+
+ if (!have_innodb($link))
+ die(sprintf("Needs InnoDB support, [%d] %s", $link->errno, $link->error));
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ if (!$mysqli = new my_mysqli($host, $user, $passwd, $db, $port, $socket)) {
+ printf("[001] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+ }
+
+ if (!is_bool($tmp = $mysqli->autocommit(true)))
+ printf("[002] Expecting boolean/any, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$mysqli->query('SET AUTOCOMMIT = 0'))
+ printf("[003] [%d] %s\n", $mysqli->errno, $mysqli->error);
+
+ if (!$res = $mysqli->query('SELECT @@autocommit as auto_commit'))
+ printf("[004] [%d] %s\n", $mysqli->errno, $mysqli->error);
+
+ $tmp = $res->fetch_assoc();
+ $res->free_result();
+ if ($tmp['auto_commit'])
+ printf("[005] Cannot turn off autocommit\n");
+
+ if (true !== ($tmp = $mysqli->autocommit( true)))
+ printf("[006] Expecting true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$res = $mysqli->query('SELECT @@autocommit as auto_commit'))
+ printf("[007] [%d] %s\n", $mysqli->errno, $mysqli->error);
+ $tmp = $res->fetch_assoc();
+ $res->free_result();
+ if (!$tmp['auto_commit'])
+ printf("[008] Cannot turn on autocommit\n");
+
+ if (!$mysqli->query('DROP TABLE IF EXISTS test'))
+ printf("[009] [%d] %s\n", $mysqli->errno, $mysqli->error);
+
+ if (!$mysqli->query('CREATE TABLE test(id INT) ENGINE = InnoDB')) {
+ printf("[010] Cannot create test table, [%d] %s\n", $mysqli->errno, $mysqli->error);
+ }
+
+ if (!$mysqli->query('INSERT INTO test(id) VALUES (1)'))
+ printf("[011] [%d] %s\n", $mysqli->errno, $mysqli->error);
+
+ if (!$mysqli->query('ROLLBACK'))
+ printf("[012] [%d] %s\n", $mysqli->errno, $mysqli->error);
+
+ if (!$res = $mysqli->query('SELECT COUNT(*) AS num FROM test'))
+ printf("[013] [%d] %s\n", $mysqli->errno, $mysqli->error);
+
+ if ((!$tmp = $res->fetch_assoc()) || (1 != $tmp['num']))
+ printf("[014] Expecting 1 row in table test, found %d rows. [%d] %s\n",
+ $tmp['num'], $mysqli->errno, $mysqli->error);
+
+ $res->free_result();
+
+ if (!$mysqli->query('DROP TABLE IF EXISTS test'))
+ printf("[015] [%d] %s\n", $mysqli->errno, $mysqli->error);
+
+ if (!$mysqli->query('SET AUTOCOMMIT = 1'))
+ printf("[016] [%d] %s\n", $mysqli->errno, $mysqli->error);
+
+ if (!$res = $mysqli->query('SELECT @@autocommit as auto_commit'))
+ printf("[017] [%d] %s\n", $mysqli->errno, $mysqli->error);
+
+ $tmp = $res->fetch_assoc();
+ $res->free_result();
+ if (!$tmp['auto_commit'])
+ printf("[018] Cannot turn on autocommit\n");
+
+ if (true !== ($tmp = $mysqli->autocommit( false)))
+ printf("[019] Expecting true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$mysqli->query('CREATE TABLE test(id INT) ENGINE = InnoDB')) {
+ printf("[020] Cannot create test table, [%d] %s\n", $mysqli->errno, $mysqli->error);
+ }
+
+ if (!$mysqli->query('INSERT INTO test(id) VALUES (1)'))
+ printf("[021] [%d] %s\n", $mysqli->errno, $mysqli->error);
+
+ if (!$mysqli->query('ROLLBACK'))
+ printf("[022] [%d] %s\n", $mysqli->errno, $mysqli->error);
+
+ if (!$res = $mysqli->query('SELECT COUNT(*) AS num FROM test'))
+ printf("[023] [%d] %s\n", $mysqli->errno, $mysqli->error);
+ $tmp = $res->fetch_assoc();
+ if (0 != $tmp['num'])
+ printf("[24] Expecting 0 rows in table test, found %d rows\n", $tmp['num']);
+ $res->free_result();
+
+ if (!$mysqli->query('INSERT INTO test(id) VALUES (1)'))
+ printf("[025] [%d] %s\n", $mysqli->errno, $mysqli->error);
+
+ if (!$mysqli->query('COMMIT'))
+ printf("[025] [%d] %s\n", $mysqli->errno, $mysqli->error);
+
+ if (!$res = $mysqli->query('SELECT COUNT(*) AS num FROM test'))
+ printf("[027] [%d] %s\n", $mysqli->errno, $mysqli->error);
+
+ if ((!$tmp = $res->fetch_assoc()) || (1 != $tmp['num']))
+ printf("[028] Expecting 1 row in table test, found %d rows. [%d] %s\n",
+ $tmp['num'], $mysqli->errno, $mysqli->error);
+ $res->free_result();
+
+ if (!$mysqli->query('DROP TABLE IF EXISTS test'))
+ printf("[029] [%d] %s\n", $mysqli->errno, $mysqli->error);
+
+ $mysqli->close();
+
+ if (NULL !== ($tmp = @$mysqli->autocommit( false)))
+ printf("[030] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_change_user.phpt b/ext/mysqli/tests/mysqli_change_user.phpt
new file mode 100644
index 0000000..bfea423
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_change_user.phpt
@@ -0,0 +1,112 @@
+--TEST--
+mysqli_change_user()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_change_user()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_change_user($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_change_user($link, $link)))
+ printf("[003] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_change_user($link, $link, $link)))
+ printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_change_user($link, $link, $link, $link, $link)))
+ printf("[005] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[006] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ if (false !== ($tmp = mysqli_change_user($link, $user . '_unknown_really', $passwd . 'non_empty', $db)))
+ printf("[007] Expecting false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (false !== ($tmp = mysqli_change_user($link, $user, $passwd . '_unknown_really', $db)))
+ printf("[008] Expecting false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (false !== ($tmp = mysqli_change_user($link, $user, $passwd, $db . '_unknown_really')))
+ printf("[009] Expecting false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_query($link, 'SET @mysqli_change_user_test_var=1'))
+ printf("[010] Failed to set test variable: [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$res = mysqli_query($link, 'SELECT @mysqli_change_user_test_var AS test_var'))
+ printf("[011] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ $tmp = mysqli_fetch_assoc($res);
+ mysqli_free_result($res);
+ if (1 != $tmp['test_var'])
+ printf("[012] Cannot set test variable\n");
+
+ if (true !== ($tmp = mysqli_change_user($link, $user, $passwd, $db)))
+ printf("[013] Expecting true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$res = mysqli_query($link, 'SELECT database() AS dbname, user() AS user'))
+ printf("[014] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ $tmp = mysqli_fetch_assoc($res);
+ mysqli_free_result($res);
+
+ if (substr($tmp['user'], 0, strlen($user)) !== $user)
+ printf("[015] Expecting user %s, got user() %s\n", $user, $tmp['user']);
+ if ($tmp['dbname'] != $db)
+ printf("[016] Expecting database %s, got database() %s\n", $db, $tmp['dbname']);
+
+ if (!$res = mysqli_query($link, 'SELECT @mysqli_change_user_test_var AS test_var'))
+ printf("[017] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ $tmp = mysqli_fetch_assoc($res);
+ mysqli_free_result($res);
+ if (NULL !== $tmp['test_var'])
+ printf("[019] Test variable is still set!\n");
+
+ mysqli_close($link);
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ printf("[020] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+ }
+
+ if (false !== ($tmp = mysqli_change_user($link, str_repeat('user', 16384), str_repeat('pass', 16384), str_repeat('dbase', 16384))))
+ printf("[021] Expecting false, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_close($link);
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ printf("[022] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+ }
+
+ /* silent protocol change if no db which requires workaround in mysqlnd/libmysql
+ (empty db = no db send with COM_CHANGE_USER) */
+ if (true !== ($tmp = mysqli_change_user($link, $user, $passwd, "")))
+ printf("[023] Expecting true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$res = mysqli_query($link, 'SELECT database() AS dbname, user() AS user'))
+ printf("[024] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ $tmp = mysqli_fetch_assoc($res);
+ mysqli_free_result($res);
+
+ if ($tmp['dbname'] != "")
+ printf("[025] Expecting database '', got database() '%s'\n", $tmp['dbname']);
+
+ mysqli_close($link);
+
+ if (NULL !== ($tmp = @mysqli_change_user($link, $user, $passwd, $db)))
+ printf("[026] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_change_user_get_lock.phpt b/ext/mysqli/tests/mysqli_change_user_get_lock.phpt
new file mode 100644
index 0000000..4cc071d
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_change_user_get_lock.phpt
@@ -0,0 +1,106 @@
+--TEST--
+mysqli_change_user() - GET_LOCK()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+die("skip - is the server still buggy?");
+?>
+--INI--
+max_execution_time=240
+--FILE--
+<?php
+ require_once('connect.inc');
+ require_once('table.inc');
+
+ // We need this little hack to be able to re-run the test
+ $lock = 'phptest_' . mt_rand(0, 100000);
+ $thread_id = mysqli_thread_id($link);
+
+ printf("Testing GET_LOCK()...\n");
+
+ if (!$res = mysqli_query($link, sprintf('SELECT GET_LOCK("%s", 2) AS _ok', $lock)))
+ printf("[001] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$row = mysqli_fetch_assoc($res))
+ printf("[002] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if ($row['_ok'] != 1)
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ else
+ printf("... lock '%s' acquired by thread %d\n", $lock, $thread_id);
+
+ mysqli_free_result($res);
+
+
+ // GET_LOCK("phptest") should be released
+ /* From the mysql_change_user documentation:
+This command resets the state as if one had done a new connect. (See Section 25.2.13, “Controlling Automatic Reconnect Behaviorâ€.) It always performs a ROLLBACK of any active transactions, closes and drops all temporary tables, and unlocks all locked tables. Session system variables are reset to the values of the corresponding global system variables. Prepared statements are released and HANDLER variables are closed. Locks acquired with GET_LOCK() are released. These effects occur even if the user didn't change.
+ */
+ mysqli_change_user($link, $user, $passwd, $db);
+sleep(5);
+ $new_thread_id = mysqli_thread_id($link);
+
+ printf("... calling IS_USED_LOCK() on '%s' using thread '%d'\n", $lock, $new_thread_id);
+ if (!$res = mysqli_query($link, 'SELECT IS_USED_LOCK("phptest") AS _ok'))
+ printf("[004] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$row = mysqli_fetch_assoc($res))
+ printf("[005] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if ($row['_ok'] != NULL)
+ printf("[006] Lock '%s' should have been released, [%d] %s\n",
+ $lock,
+ mysqli_errno($link), mysqli_error($link));
+
+ printf("... calling IS_FREE_LOCK() on '%s' using thread '%d'\n", $lock, $new_thread_id);
+ if (!$res = mysqli_query($link, 'SELECT IS_FREE_LOCK("phptest") AS _ok'))
+ printf("[007] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$row = mysqli_fetch_assoc($res))
+ printf("[008] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if ($row['_ok'] != 1)
+ printf("[009] Lock '%s' should have been released, [%d] %s\n",
+ $lock,
+ mysqli_errno($link), mysqli_error($link));
+
+ mysqli_free_result($res);
+
+ /* Ok, let's try a NEW connection and a NEW lock! */
+ mysqli_close($link);
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[010] Cannot open new connection, [%d] %s\n",
+ mysqli_connect_errno(), mysqli_connect_error());
+
+ do {
+ $newlock = 'phptest_' . mt_rand(0, 100000);
+ } while ($lock == $newlock);
+
+ $new_thread_id = mysqli_thread_id($link);
+ printf("... calling IS_USED_LOCK() on '%s' using new connection with thread '%d'\n", $newlock, $new_thread_id);
+ if (!$res = mysqli_query($link, 'SELECT IS_USED_LOCK("phptest") AS _ok'))
+ printf("[011] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$row = mysqli_fetch_assoc($res))
+ printf("[012] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if ($row['_ok'] != NULL)
+ printf("[013] Lock '%s' should have been released, [%d] %s\n",
+ $lock,
+ mysqli_errno($link), mysqli_error($link));
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Testing GET_LOCK()...
+... lock 'phptest_%d' acquired by thread %d
+... calling IS_USED_LOCK() on 'phptest_%d' using thread '%d'
+... calling IS_FREE_LOCK() on 'phptest_%d' using thread '%d'
+... calling IS_USED_LOCK() on 'phptest_%d' using new connection with thread '%d'
+done!
diff --git a/ext/mysqli/tests/mysqli_change_user_insert_id.phpt b/ext/mysqli/tests/mysqli_change_user_insert_id.phpt
new file mode 100644
index 0000000..7d1c398
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_change_user_insert_id.phpt
@@ -0,0 +1,65 @@
+--TEST--
+mysqli_change_user() - LAST_INSERT_ID() - http://bugs.mysql.com/bug.php?id=45184?
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+require_once('connect.inc');
+
+if (!$IS_MYSQLND) {
+ die("skip Might hit known and open bugs http://bugs.mysql.com/bug.php?id=30472, http://bugs.mysql.com/bug.php?id=45184");
+}
+?>
+--FILE--
+<?php
+ require_once('connect.inc');
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+ if (!mysqli_query($link, 'DROP TABLE IF EXISTS test'))
+ printf("[002] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, 'CREATE TABLE test(id INT AUTO_INCREMENT PRIMARY KEY, label CHAR(10))'))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, "INSERT INTO test(id, label) VALUES (100, 'z')"))
+ printf("[004] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (($insert_id = mysqli_insert_id($link)) !== 100)
+ printf("[005] Expecting 100, got %d, [%d] %s\n",
+ $insert_id,
+ mysqli_errno($link), mysqli_error($link));
+
+ // LAST_INSERT_ID should be reset
+ mysqli_change_user($link, $user, $passwd, $db);
+
+ if (($insert_id = mysqli_insert_id($link)) !== 0)
+ printf("[006] Expecting 0, got %d, [%d] %s\n",
+ $insert_id,
+ mysqli_errno($link), mysqli_error($link));
+
+ if (!$res = mysqli_query($link, 'SELECT LAST_INSERT_ID() as _insert_id'))
+ printf("[007] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$row = mysqli_fetch_assoc($res))
+ printf("[008] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ mysqli_free_result($res);
+
+ if ($row['_insert_id'] != $insert_id)
+ printf("LAST_INSERT_ID() [%d] and mysqli_insert_id [%d] differ!\n",
+ $row['_insert_id'], $insert_id);
+
+ if ($row['_insert_id'] != 0)
+ printf("Expecting 0 got %d\n", $row['_insert_id']);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_change_user_locks_temporary.phpt b/ext/mysqli/tests/mysqli_change_user_locks_temporary.phpt
new file mode 100644
index 0000000..e40154c
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_change_user_locks_temporary.phpt
@@ -0,0 +1,107 @@
+--TEST--
+mysqli_change_user() - table locks, GET_LOCK(), temporary tables
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+die("skip - is the server still buggy?");
+?>
+--FILE--
+<?php
+ require_once('connect.inc');
+ require_once('table.inc');
+
+ if (!$link2 = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[001] Cannot create second connection handle, [%d] %s\n",
+ mysqli_connect_errno(), mysqli_connect_error());
+
+ if (!mysqli_query($link, 'LOCK TABLE test WRITE'))
+ printf("[002] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ /*
+ if ($res = mysqli_query($link2, 'SELECT COUNT(*) AS _num FROM test')) {
+ printf("[003] Reading from test should not be possible due to a lock, [%d] %s\n",
+ mysqli_errno($link2), mysqli_error($link2));
+ mysqli_free_result($res);
+ }
+ */
+
+ // LOCKS should be removed
+ mysqli_change_user($link, $user, $passwd, $db);
+
+ if (!$res = mysqli_query($link2, 'SELECT COUNT(*) AS _num FROM test'))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$row = mysqli_fetch_assoc($res))
+ printf("[004] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if ($row['_num'] < 1)
+ printf("[005] There should be some rows in the table test\n");
+
+ mysqli_free_result($res);
+ mysqli_close($link2);
+
+ if (!mysqli_query($link, 'DROP TABLE test'))
+ printf("[006] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, 'CREATE TEMPORARY TABLE test(id INT)'))
+ printf("[007] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, 'INSERT INTO test(id) VALUES (1), (2), (3)'))
+ printf("[008] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$res = mysqli_query($link, 'SELECT COUNT(*) AS _num FROM test'))
+ printf("[009] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$row = mysqli_fetch_assoc($res))
+ printf("[010] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if ($row['_num'] != 3)
+ printf("[011] There should be three rows in the table test\n");
+
+ mysqli_free_result($res);
+
+ // Temporary tables should be dropped
+ mysqli_change_user($link, $user, $passwd, $db);
+
+ if ($res = mysqli_query($link, 'SELECT COUNT(*) AS _num FROM test')) {
+ printf("[012] There should be no table test any more, [%d] %s\n",
+ mysqli_errno($link), mysqli_error($link));
+ mysqli_free_result($res);
+ }
+
+ if (!$res = mysqli_query($link, 'SELECT GET_LOCK("phptest", 2) AS _ok'))
+ printf("[013] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$row = mysqli_fetch_assoc($res))
+ printf("[014] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if ($row['_ok'] != 1)
+ printf("[015] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ mysqli_free_result($res);
+
+ // GET_LOCK("phptest") should be released
+ mysqli_change_user($link, $user, $passwd, $db);
+
+ if (!$res = mysqli_query($link, 'SELECT IS_FREE_LOCK("phptest") AS _ok'))
+ printf("[016] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$row = mysqli_fetch_assoc($res))
+ printf("[017] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if ($row['_ok'] != 1)
+ printf("[018] Lock 'phptest' should have been released, [%d] %s\n",
+ mysqli_errno($link), mysqli_error($link));
+
+ mysqli_free_result($res);
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+done!
diff --git a/ext/mysqli/tests/mysqli_change_user_oo.phpt b/ext/mysqli/tests/mysqli_change_user_oo.phpt
new file mode 100644
index 0000000..61444ae
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_change_user_oo.phpt
@@ -0,0 +1,84 @@
+--TEST--
+mysqli->change_user()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+require_once('table.inc');
+if (!$IS_MYSQLND && (mysqli_get_server_version($link) < 50118 && mysqli_get_server_version($link) > 50100)) {
+ die("skip Your MySQL Server version has a known bug that will cause a crash");
+}
+?>
+--FILE--
+<?php
+ include_once("connect.inc");
+
+ $link = NULL;
+ $tmp = NULL;
+
+ if (!$mysqli = new my_mysqli($host, $user, $passwd, $db, $port, $socket))
+ printf("[001] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ if (!is_null($tmp = @$mysqli->change_user()))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @$mysqli->change_user($link)))
+ printf("[003] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @$mysqli->change_user($link, $link)))
+ printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @$mysqli->change_user($link, $link, $link, $link)))
+ printf("[005] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (false !== ($tmp = $mysqli->change_user($user . '_unknown_really', $passwd . 'non_empty', $db)))
+ printf("[006] Expecting false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (false !== ($tmp = $mysqli->change_user($user, $passwd . '_unknown_really', $db)))
+ printf("[007] Expecting false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (false !== ($tmp = $mysqli->change_user($user, $passwd, $db . '_unknown_really')))
+ printf("[008] Expecting false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$mysqli->query('SET @mysqli_change_user_test_var=1'))
+ printf("[009] Failed to set test variable: [%d] %s\n", $mysqli->errno, $mysqli->error);
+
+ if (!$res = $mysqli->query('SELECT @mysqli_change_user_test_var AS test_var'))
+ printf("[010] [%d] %s\n", $mysqli->errno, $mysqli->error);
+ $tmp = $res->fetch_assoc();
+ $res->free_result();
+ if (1 != $tmp['test_var'])
+ printf("[011] Cannot set test variable\n");
+
+ if (true !== ($tmp = $mysqli->change_user($user, $passwd, $db)))
+ printf("[012] Expecting true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$res = $mysqli->query('SELECT database() AS dbname, user() AS user'))
+ printf("[013] [%d] %s\n", $mysqli->errno, $mysqli->error);
+ $tmp = $res->fetch_assoc();
+ $res->free_result();
+
+ if (substr($tmp['user'], 0, strlen($user)) !== $user)
+ printf("[014] Expecting user %s, got user() %s\n", $user, $tmp['user']);
+ if ($tmp['dbname'] != $db)
+ printf("[015] Expecting database %s, got database() %s\n", $db, $tmp['dbname']);
+
+ if (!$res = $mysqli->query('SELECT @mysqli_change_user_test_var AS test_var'))
+ printf("[016] [%d] %s\n", $mysqli->errno, $mysqli->error);
+ $tmp = $res->fetch_assoc();
+ $res->free_result();
+ if (NULL !== $tmp['test_var'])
+ printf("[017] Test variable is still set!\n");
+
+ $mysqli->close();
+
+ if (NULL !== ($tmp = @$mysqli->change_user($user, $passwd, $db)))
+ printf("[018] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_change_user_prepared_statements.phpt b/ext/mysqli/tests/mysqli_change_user_prepared_statements.phpt
new file mode 100644
index 0000000..6a37b6b
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_change_user_prepared_statements.phpt
@@ -0,0 +1,33 @@
+--TEST--
+mysqli_change_user() - Prepared Statement
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once('connect.inc');
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+ if (!$stmt = mysqli_prepare($link, "SELECT 'prepared statements should be released'"))
+ printf("[002] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+ mysqli_change_user($link, $user, $passwd, $db);
+
+ $wrong = null;
+ if ($stmt->execute() && $stmt->bind_result($wrong) && $stmt->fetch()) {
+ printf("This is wrong, because after a mysqli_change_user() %s\n", $wrong);
+ } else {
+ if ($stmt->errno == 0)
+ printf("Error code 2013, 1243 or similar should have been set\n");
+ }
+
+ mysqli_close($link);
+ print "done!";
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_change_user_rollback.phpt b/ext/mysqli/tests/mysqli_change_user_rollback.phpt
new file mode 100644
index 0000000..ed3330e
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_change_user_rollback.phpt
@@ -0,0 +1,70 @@
+--TEST--
+mysqli_change_user() - ROLLBACK
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+require_once('connect.inc');
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ die(sprintf("Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error()));
+
+if (!have_innodb($link))
+ die(sprintf("Needs InnoDB support, [%d] %s", $link->errno, $link->error));
+?>
+--FILE--
+<?php
+ require_once('connect.inc');
+ require_once('table.inc');
+
+ if (!mysqli_query($link, 'ALTER TABLE test ENGINE=InnoDB'))
+ printf("[001] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ mysqli_autocommit($link, false);
+
+ if (!$res = mysqli_query($link, 'SELECT COUNT(*) AS _num FROM test'))
+ printf("[002] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$row = mysqli_fetch_assoc($res))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ mysqli_free_result($res);
+
+ $num = $row['_num'];
+ assert($num > 0);
+
+ if (!$res = mysqli_query($link, 'DELETE FROM test'))
+ printf("[004] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$res = mysqli_query($link, 'SELECT COUNT(*) AS _num FROM test'))
+ printf("[005] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$row = mysqli_fetch_assoc($res))
+ printf("[006] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ mysqli_free_result($res);
+
+ if (0 != $row['_num'])
+ printf("[007] Rows should have been deleted in this transaction\n");
+
+ // DELETE should be rolled back
+ mysqli_change_user($link, $user, $passwd, $db);
+
+ if (!$res = mysqli_query($link, 'SELECT COUNT(*) AS _num FROM test'))
+ printf("[008] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$row = mysqli_fetch_assoc($res))
+ printf("[009] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if ($row['_num'] != $num)
+ printf("[010] Expecting %d rows in the table test, found %d rows\n",
+ $num, $row['_num']);
+
+ mysqli_free_result($res);
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_change_user_set_names.phpt b/ext/mysqli/tests/mysqli_change_user_set_names.phpt
new file mode 100644
index 0000000..3579e31
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_change_user_set_names.phpt
@@ -0,0 +1,165 @@
+--TEST--
+mysqli_change_user() - SET NAMES
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ die(sprintf("skip [%d] %s", mysqli_connect_errno(), mysqli_connect_error()));
+
+if (!$res = mysqli_query($link, 'SELECT version() AS server_version'))
+ die(sprintf("skip [%d] %s\n", mysqli_errno($link), mysqli_error($link)));
+
+$tmp = mysqli_fetch_assoc($res);
+mysqli_free_result($res);
+$version = explode('.', $tmp['server_version']);
+if (empty($version))
+ die(sprintf("skip Cannot determine server version, we need MySQL Server 4.1+ for the test!"));
+
+if ($version[0] <= 4 && $version[1] < 1)
+ die(sprintf("skip We need MySQL Server 4.1+ for the test!"));
+?>
+--FILE--
+<?php
+ require_once('connect.inc');
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+ if (!$res = mysqli_query($link, "SHOW CHARACTER SET LIKE 'latin%'"))
+ printf("[002] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $charsets = array();
+ while ($row = mysqli_fetch_assoc($res))
+ $charsets[$row['Charset']] = $row['Default collation'];
+
+ mysqli_free_result($res);
+ if (!mysqli_query($link, 'SET NAMES DEFAULT'))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$res = mysqli_query($link, 'SELECT
+ @@character_set_client AS charset_client,
+ @@character_set_connection AS charset_connection,
+ @@character_set_results AS charset_results,
+ @@collation_connection AS collation_connection,
+ @@collation_database AS collation_database,
+ @@collation_server AS collation_server'))
+ printf("[004] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$defaults = mysqli_fetch_assoc($res))
+ printf("[005] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ mysqli_free_result($res);
+
+ $not_changed = $defaults;
+ foreach ($charsets as $charset => $collation) {
+
+ if (isset($not_changed['charset_client']) &&
+ $charset != $not_changed['charset_client'] &&
+ mysqli_query($link, sprintf("SET @@character_set_client = '%s'", $charset)))
+ unset($not_changed['charset_client']);
+
+ if (isset($not_changed['charset_connection']) &&
+ $charset != $not_changed['charset_connection'] &&
+ mysqli_query($link, sprintf("SET @@character_connection = '%s'", $charset)))
+ unset($not_changed['charset_connection']);
+
+ if (isset($not_changed['charset_results']) &&
+ $charset != $not_changed['charset_results'] &&
+ mysqli_query($link, sprintf("SET @@character_set_results = '%s'", $charset)))
+ unset($not_changed['charset_results']);
+
+ if (isset($not_changed['collation_connection']) &&
+ $collation != $not_changed['collation_connection'] &&
+ mysqli_query($link, sprintf("SET @@collation_connection = '%s'", $collation)))
+ unset($not_changed['collation_connection']);
+
+ if (isset($not_changed['collation_database']) &&
+ $collation != $not_changed['collation_database'] &&
+ mysqli_query($link, sprintf("SET @@collation_database = '%s'", $collation)))
+ unset($not_changed['collation_database']);
+
+ if (isset($not_changed['collation_server']) &&
+ $collation != $not_changed['collation_server'] &&
+ mysqli_query($link, sprintf("SET @@collation_server = '%s'", $collation)))
+ unset($not_changed['collation_server']);
+
+ if (empty($not_changed))
+ break;
+ }
+
+ if (!$res = mysqli_query($link, 'SELECT
+ @@character_set_client AS charset_client,
+ @@character_set_connection AS charset_connection,
+ @@character_set_results AS charset_results,
+ @@collation_connection AS collation_connection,
+ @@collation_database AS collation_database,
+ @@collation_server AS collation_server'))
+ printf("[006] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$modified = mysqli_fetch_assoc($res))
+ printf("[007] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ mysqli_free_result($res);
+
+ if ($modified == $defaults)
+ printf("[008] Not all settings have been changed\n");
+
+ // LAST_INSERT_ID should be reset
+ mysqli_change_user($link, $user, $passwd, $db);
+
+ if (!$res = mysqli_query($link, 'SELECT
+ @@character_set_client AS charset_client,
+ @@character_set_connection AS charset_connection,
+ @@character_set_results AS charset_results,
+ @@collation_connection AS collation_connection,
+ @@collation_database AS collation_database,
+ @@collation_server AS collation_server'))
+ printf("[009] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$new = mysqli_fetch_assoc($res))
+ printf("[010] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ mysqli_free_result($res);
+
+ if ($new == $modified) {
+ printf("[011] Charsets/collations have not been reset.\n");
+ printf("Got:\n");
+ var_dump($new);
+ printf("Expected:\n");
+ var_dump($defaults);
+ }
+
+ if ((version_compare(PHP_VERSION, '5.9.9', '>') == 1)) {
+ // charsets cannot take any other value but utf8 in unicode mode
+ $defaults['charset_client'] = 'utf8';
+ $defaults['charset_connection'] = 'utf8';
+ $defaults['charset_results'] = 'utf8';
+ $defaults['collation_connection'] = 'utf8_general_ci';
+ }
+
+ if ($new != $defaults) {
+ printf("[012] Charsets/collations have not been reset to their defaults.\n");
+ printf("Got:\n");
+ var_dump($new);
+ printf("Expected:\n");
+ var_dump($defaults);
+ }
+
+ if (!is_object($charset = mysqli_get_charset($link)))
+ printf("[013] Expecting object/std_class, got %s/%s\n", gettype($charset), $charset);
+
+ if ($charset->charset != $defaults['charset_connection'])
+ printf("[014] Expecting connection charset to be %s got %s\n",
+ $defaults['charset_connection'],
+ $charset->charset);
+
+ if ($charset->collation != $defaults['collation_connection'])
+ printf("[015] Expecting collation to be %s got %s\n",
+ $defaults['collation_connection'],
+ $charset->collation);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_character_set.phpt b/ext/mysqli/tests/mysqli_character_set.phpt
new file mode 100644
index 0000000..1bfe9cb
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_character_set.phpt
@@ -0,0 +1,111 @@
+--TEST--
+Fetching results from tables of different charsets.
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+require_once('skipifunicode.inc');
+require_once('skipifemb.inc');
+
+if (!function_exists('mysqli_set_charset')) {
+ die('skip mysqli_set_charset() not available');
+}
+if (version_compare(PHP_VERSION, '5.9.9', '>') == 1) {
+ die('skip set character set not functional with PHP 6 (fomerly PHP 6 && unicode.semantics=On)');
+}
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[001] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ if (!$res = mysqli_query($link, 'SELECT version() AS server_version'))
+ printf("[002] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ $tmp = mysqli_fetch_assoc($res);
+ mysqli_free_result($res);
+ $version = explode('.', $tmp['server_version']);
+ if (empty($version))
+ printf("[003] Cannot determine server version, need MySQL Server 4.1+ for the test!\n");
+
+ if ($version[0] <= 4 && $version[1] < 1)
+ printf("[004] Need MySQL Server 4.1+ for the test!\n");
+
+ if (!$res = mysqli_query($link, "SHOW CHARACTER SET"))
+ printf("[005] Cannot get list of available character sets, [%d] %s\n",
+ mysqli_errno($link), mysqli_error($link));
+
+ $charsets = array();
+ while ($row = mysqli_fetch_assoc($res))
+ $charsets[] = $row;
+ mysqli_free_result($res);
+
+ foreach ($charsets as $charset) {
+ $k = $charset['Charset'];
+ /* The server currently 17.07.2007 can't handle data sent in ucs2 */
+ /* The server currently 16.08.2010 can't handle data sent in utf16 and utf32 */
+ /* The server currently 02.09.2011 can't handle data sent in utf16le */
+ if ($charset['Charset'] == 'ucs2' || $charset['Charset'] == 'utf16' || $charset['Charset'] == 'utf32' || 'utf16le' == $charset['Charset']) {
+ continue;
+ }
+
+ if (!mysqli_query($link, "DROP TABLE IF EXISTS test"))
+ printf("[006 + %s] [%d] %s\n", $k, mysqli_errno($link), mysqli_error($link));
+
+ $sql = sprintf("CREATE TABLE test(id INT, label CHAR(1)) CHARACTER SET '%s' ", $charset['Charset']);
+ if (!mysqli_query($link, $sql)) {
+ printf("[007 + %s] %s [%d] %s\n", $k, $sql, mysqli_errno($link), mysqli_error($link));
+ continue;
+ }
+
+ if (!mysqli_set_charset($link, $charset['Charset'])) {
+ printf("[008 + %s] [%d] %s\n", $k, mysqli_errno($link), mysqli_error($link));
+ continue;
+ }
+
+ for ($i = 1; $i <= 3; $i++) {
+ if (!mysqli_query($link, sprintf("INSERT INTO test (id, label) VALUES (%d, '%s')",
+ $i, mysqli_real_escape_string($link, chr(ord("a") + $i)))))
+ {
+ var_dump($charset['Charset']);
+ printf("[009 + %s] [%d] %s\n", $k, mysqli_errno($link), mysqli_error($link));
+ continue;
+ }
+ }
+
+ if (!$res = mysqli_query($link, "SELECT id, label FROM test"))
+ printf("[010 + %s] [%d] %s\n", $k, mysqli_errno($link), mysqli_error($link));
+
+ for ($i = 1; $i <= 3; $i++) {
+
+ if (!$tmp = mysqli_fetch_assoc($res))
+ printf("[011 + %s] [%d] %s\n", $k, mysqli_errno($link), mysqli_error($link));
+
+ if ($tmp['id'] != $i)
+ printf("[012 + %s] Expecting %d, got %s, [%d] %s\n", $k,
+ $i, $tmp['id'],
+ mysqli_errno($link), mysqli_error($link));
+
+ if ($tmp['label'] != chr(ord("a") + $i))
+ printf("[013 + %s] Expecting %d, got %s, [%d] %s\n", $k,
+ chr(ord("a") + $i), $tmp['label'],
+ mysqli_errno($link), mysqli_error($link));
+
+ }
+ mysqli_free_result($res);
+ }
+
+ mysqli_close($link);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+done!
diff --git a/ext/mysqli/tests/mysqli_character_set_name.phpt b/ext/mysqli/tests/mysqli_character_set_name.phpt
new file mode 100644
index 0000000..722faca
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_character_set_name.phpt
@@ -0,0 +1,75 @@
+--TEST--
+mysqli_chararcter_set_name(), mysql_client_encoding() [alias]
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ /* NOTE: http://bugs.mysql.com/bug.php?id=7923 makes this test fail very likely on all 4.1.x - 5.0.x! */
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_character_set_name()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_character_set_name($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_character_set_name($link, $link, $link)))
+ printf("[003] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[005] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ if (!$res = mysqli_query($link, 'SELECT version() AS server_version'))
+ printf("[005] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ $tmp = mysqli_fetch_assoc($res);
+ mysqli_free_result($res);
+ $version = explode('.', $tmp['server_version']);
+ if (empty($version))
+ printf("[006] Cannot determine server version, need MySQL Server 4.1+ for the test!\n");
+
+ if ($version[0] <= 4 && $version[1] < 1)
+ printf("[007] Need MySQL Server 4.1+ for the test!\n");
+
+ if (!$res = mysqli_query($link, 'SELECT @@character_set_connection AS charset, @@collation_connection AS collation'))
+ printf("[008] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ $tmp = mysqli_fetch_assoc($res);
+ mysqli_free_result($res);
+ if (!$tmp['charset'])
+ printf("[009] Cannot determine current character set and collation\n");
+
+ $charset = mysqli_character_set_name($link);
+ if ($tmp['charset'] !== $charset) {
+ if ($tmp['collation'] === $charset) {
+ printf("[010] Could be known server bug http://bugs.mysql.com/bug.php?id=7923, collation %s instead of character set returned, expected string/%s, got %s/%s\n",
+ $tmp['collation'], $tmp['charset'], gettype($charset), $charset);
+ } else {
+ printf("[011] Expecting character set %s/%s, got %s/%s\n", gettype($tmp['charset']), $tmp['charset'], gettype($charset), $charset);
+ }
+ }
+
+ $charset2 = mysqli_character_set_name($link);
+ if ($charset2 !== $charset) {
+ printf("[012] Alias mysqli_character_set_name returned %s/%s, expected %s/%s\n", gettype($charset2), $charset2, gettype($charset), $charset);
+ }
+
+ mysqli_close($link);
+
+ if (NULL !== ($tmp = @mysqli_character_set_name($link)))
+ printf("[013] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ /* Make sure that the function alias exists */
+ if (!is_null($tmp = @mysqli_character_set_name()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_character_set_name_oo.phpt b/ext/mysqli/tests/mysqli_character_set_name_oo.phpt
new file mode 100644
index 0000000..7b71940
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_character_set_name_oo.phpt
@@ -0,0 +1,70 @@
+--TEST--
+mysqli_chararcter_set_name(), mysql_client_encoding() [alias]
+--SKIPIF--
+<?php
+ require_once('skipif.inc');
+ require_once('skipifemb.inc');
+ require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ /* NOTE: http://bugs.mysql.com/bug.php?id=7923 makes this test fail very likely on all 4.1.x - 5.0.x! */
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!$mysqli = new my_mysqli($host, $user, $passwd, $db, $port, $socket))
+ printf("[001] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ if (!is_null($tmp = @$mysqli->character_set_name($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$res = $mysqli->query('SELECT version() AS server_version'))
+ printf("[003] [%d] %s\n", $mysqli->errno, $mysqli->error);
+ $tmp = $res->fetch_assoc();
+ $res->free_result();
+ $version = explode('.', $tmp['server_version']);
+ if (empty($version))
+ printf("[006] Cannot determine server version, need MySQL Server 4.1+ for the test!\n");
+
+ if ($version[0] <= 4 && $version[1] < 1)
+ printf("[007] Need MySQL Server 4.1+ for the test!\n");
+
+ if (!$res = $mysqli->query('SELECT @@character_set_connection AS charset, @@collation_connection AS collation'))
+ printf("[008] [%d] %s\n", $mysqli->errno, $mysqli->error);
+ $tmp = $res->fetch_assoc();
+ $res->free_result();
+ if (!$tmp['charset'])
+ printf("[009] Cannot determine current character set and collation\n");
+
+ $charset = $mysqli->character_set_name();
+ if ($tmp['charset'] !== $charset) {
+ if ($tmp['collation'] === $charset) {
+ printf("[010] Could be known server bug http://bugs.mysql.com/bug.php?id=7923, collation %s instead of character set returned, expected string/%s, got %s/%s\n",
+ $tmp['collation'], $tmp['charset'], gettype($charset), $charset);
+ } else {
+ printf("[011] Expecting character set %s/%s, got %s/%s\n", gettype($tmp['charset']), $tmp['charset'], gettype($charset), $charset);
+ }
+ }
+
+ $charset2 = $mysqli->character_set_name();
+ if ($charset2 !== $charset) {
+ printf("[012] Alias mysqli_character_set_name returned %s/%s, expected %s/%s\n",
+ gettype($charset2), $charset2, gettype($charset), $charset);
+ }
+
+ $mysqli->close();
+
+ if (NULL !== ($tmp = @$mysqli->character_set_name()))
+ printf("[013] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ /* Make sure that the function alias exists */
+ if (!is_null($tmp = @$mysqli->character_set_name()))
+ printf("[014] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_class_mysqli_driver_interface.phpt b/ext/mysqli/tests/mysqli_class_mysqli_driver_interface.phpt
new file mode 100644
index 0000000..681590e
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_class_mysqli_driver_interface.phpt
@@ -0,0 +1,128 @@
+--TEST--
+Interface of the class mysqli_driver
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require('connect.inc');
+ require('table.inc');
+
+ $driver = new mysqli_driver();
+
+ printf("Parent class:\n");
+ var_dump(get_parent_class($driver));
+
+ printf("\nMethods:\n");
+ $methods = get_class_methods($driver);
+ $expected_methods = array();
+
+ if (!$IS_MYSQLND && (isset($methods['embedded_server_start']))) {
+ /* libmysql only - needs extra compile flag, no way to check properly in the
+ PHP user land if its compiled in or not */
+ $expected_methods = array_merge($expected_methods, array(
+ 'embedded_server_start' => true,
+ 'embedded_server_end' => true,
+ ));
+ }
+
+ foreach ($methods as $k => $method) {
+ if (isset($expected_methods[$method])) {
+ unset($expected_methods[$method]);
+ unset($methods[$k]);
+ }
+ }
+ if (!empty($expected_methods)) {
+ printf("Dumping list of missing methods.\n");
+ var_dump($expected_methods);
+ }
+ if (!empty($methods)) {
+ printf("Dumping list of unexpected methods.\n");
+ var_dump($methods);
+ }
+ if (empty($expected_methods) && empty($methods))
+ printf("ok\n");
+
+ printf("\nClass variables:\n");
+ $variables = array_keys(get_class_vars(get_class($driver)));
+ sort($variables);
+ foreach ($variables as $k => $var)
+ printf("%s\n", $var);
+
+ printf("\nObject variables:\n");
+ $variables = array_keys(get_object_vars($driver));
+ foreach ($variables as $k => $var)
+ printf("%s\n", $var);
+
+ printf("\nMagic, magic properties:\n");
+
+ assert(mysqli_get_client_info() === $driver->client_info);
+ printf("driver->client_info = '%s'\n", $driver->client_info);
+
+ assert(mysqli_get_client_version() === $driver->client_version);
+ printf("driver->client_version = '%s'\n", $driver->client_version);
+
+ assert($driver->driver_version > 0);
+ printf("driver->driver_version = '%s'\n", $driver->driver_version);
+
+ assert(in_array($driver->report_mode,
+ array(
+ MYSQLI_REPORT_ALL,
+ MYSQLI_REPORT_STRICT,
+ MYSQLI_REPORT_ERROR,
+ MYSQLI_REPORT_INDEX,
+ MYSQLI_REPORT_OFF
+ )
+ ));
+
+ printf("driver->report_mode = '%s'\n", $driver->report_mode);
+ $driver->report_mode = MYSQLI_REPORT_STRICT;
+ assert($driver->report_mode === MYSQLI_REPORT_STRICT);
+
+ assert(is_bool($driver->embedded));
+ printf("driver->embedded = '%s'\n", $driver->embedded);
+
+ printf("driver->reconnect = '%s'\n", $driver->reconnect);
+
+ printf("\nAccess to undefined properties:\n");
+ printf("driver->unknown = '%s'\n", @$driver->unknown);
+
+ print "done!";
+?>
+--EXPECTF--
+Parent class:
+bool(false)
+
+Methods:
+ok
+
+Class variables:
+client_info
+client_version
+driver_version
+embedded
+reconnect
+report_mode
+
+Object variables:
+client_info
+client_version
+driver_version
+embedded
+reconnect
+report_mode
+
+Magic, magic properties:
+driver->client_info = '%s'
+driver->client_version = '%d'
+driver->driver_version = '%d'
+driver->report_mode = '%d'
+driver->embedded = ''
+driver->reconnect = ''
+
+Access to undefined properties:
+driver->unknown = ''
+done!
diff --git a/ext/mysqli/tests/mysqli_class_mysqli_driver_reflection.phpt b/ext/mysqli/tests/mysqli_class_mysqli_driver_reflection.phpt
new file mode 100644
index 0000000..2e6d9c2
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_class_mysqli_driver_reflection.phpt
@@ -0,0 +1,92 @@
+--TEST--
+Interface of the class mysqli_driver - Reflection
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('connect.inc');
+if (($tmp = substr(PHP_VERSION, 0, strpos(PHP_VERSION, '.'))) && ($tmp < 5))
+ die("skip Reflection not available before PHP 5 (found PHP $tmp)");
+
+/*
+Let's not deal with cross-version issues in the EXPECTF/UEXPECTF.
+Most of the things which we test are covered by mysqli_class_*_interface.phpt.
+Those tests go into the details and are aimed to be a development tool, no more.
+*/
+if (!$IS_MYSQLND)
+ die("skip Test has been written for the latest version of mysqlnd only");
+?>
+--FILE--
+<?php
+ require_once('reflection_tools.inc');
+ $class = new ReflectionClass('mysqli_driver');
+ inspectClass($class);
+ print "done!";
+?>
+--EXPECTF--
+Inspecting class 'mysqli_driver'
+isInternal: yes
+isUserDefined: no
+isInstantiable: yes
+isInterface: no
+isAbstract: no
+isFinal: yes
+isIteratable: no
+Modifiers: '%d'
+Parent Class: ''
+Extension: 'mysqli'
+
+Inspecting property 'client_info'
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isDefault: yes
+Modifiers: 256
+
+Inspecting property 'client_version'
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isDefault: yes
+Modifiers: 256
+
+Inspecting property 'driver_version'
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isDefault: yes
+Modifiers: 256
+
+Inspecting property 'embedded'
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isDefault: yes
+Modifiers: 256
+
+Inspecting property 'reconnect'
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isDefault: yes
+Modifiers: 256
+
+Inspecting property 'report_mode'
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isDefault: yes
+Modifiers: 256
+Default property 'client_info'
+Default property 'client_version'
+Default property 'driver_version'
+Default property 'embedded'
+Default property 'reconnect'
+Default property 'report_mode'
+done!
diff --git a/ext/mysqli/tests/mysqli_class_mysqli_interface.phpt b/ext/mysqli/tests/mysqli_class_mysqli_interface.phpt
new file mode 100644
index 0000000..df7d1c6
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_class_mysqli_interface.phpt
@@ -0,0 +1,319 @@
+--TEST--
+Interface of the class mysqli
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require('connect.inc');
+
+ $mysqli = new mysqli($host, $user, $passwd, $db, $port, $socket);
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+
+ printf("Parent class:\n");
+ var_dump(get_parent_class($mysqli));
+
+ printf("\nMethods:\n");
+ $methods = get_class_methods($mysqli);
+ $expected_methods = array(
+ 'autocommit' => true,
+ 'change_user' => true,
+ 'character_set_name' => true,
+ 'close' => true,
+ 'commit' => true,
+ 'connect' => true,
+ 'dump_debug_info' => true,
+ 'escape_string' => true,
+ 'get_charset' => true,
+ 'get_client_info' => true,
+ 'get_server_info' => true,
+ 'get_warnings' => true,
+ 'init' => true,
+ 'kill' => true,
+ 'more_results' => true,
+ 'multi_query' => true,
+ 'mysqli' => true,
+ 'next_result' => true,
+ 'options' => true,
+ 'ping' => true,
+ 'prepare' => true,
+ 'query' => true,
+ 'real_connect' => true,
+ 'real_escape_string' => true,
+ 'real_query' => true,
+ 'refresh' => true,
+ 'rollback' => true,
+ 'select_db' => true,
+ 'set_charset' => true,
+ 'set_opt' => true,
+ 'ssl_set' => true,
+ 'stat' => true,
+ 'stmt_init' => true,
+ 'store_result' => true,
+ 'thread_safe' => true,
+ 'use_result' => true,
+ );
+
+ if (version_compare(PHP_VERSION, '5.3.99', '<=')) {
+ $expected_methods['client_encoding'] = true;
+ }
+
+ if ($IS_MYSQLND) {
+ // mysqlnd only
+ /* $expected_methods['get_client_stats'] = true; */
+ $expected_methods['get_connection_stats'] = true;
+ $expected_methods['reap_async_query'] = true;
+ $expected_methods['poll'] = true;
+ } else {
+ // libmysql only
+ if (function_exists('mysqli_ssl_set'))
+ $expected_methods['ssl_set'] = true;
+ $expected_methods['set_local_infile_default'] = true;
+ $expected_methods['set_local_infile_handler'] = true;
+ }
+
+ /* we should add ruled when to expect them */
+ if (function_exists('mysqli_debug'))
+ $expected_methods['debug'] = true;
+ if (function_exists('ssl_set'))
+ $expected_methods['ssl_set'] = true;
+
+ foreach ($methods as $k => $method) {
+ if (isset($expected_methods[$method])) {
+ unset($methods[$k]);
+ unset($expected_methods[$method]);
+ }
+ }
+ if (!empty($methods)) {
+ printf("Dumping list of unexpected methods.\n");
+ var_dump($methods);
+ }
+ if (!empty($expected_methods)) {
+ printf("Dumping list of missing methods.\n");
+ var_dump($expected_methods);
+ }
+ if (empty($methods) && empty($expected_methods))
+ printf("ok\n");
+
+ printf("\nClass variables:\n");
+
+ $expected_class_variables = $expected_object_variables = array(
+ "affected_rows" => true,
+ "client_info" => true,
+ "client_version" => true,
+ "connect_errno" => true,
+ "connect_error" => true,
+ "errno" => true,
+ "error" => true,
+ "field_count" => true,
+ "host_info" => true,
+ "info" => true,
+ "insert_id" => true,
+ "protocol_version" => true,
+ "server_info" => true,
+ "server_version" => true,
+ "sqlstate" => true,
+ "stat" => true,
+ "thread_id" => true,
+ "warning_count" => true,
+ );
+
+ if (version_compare(PHP_VERSION, '5.3.99', '>')) {
+ $expected_class_variables["error_list"] = true;
+ $expected_object_variables["error_list"] = true;
+ }
+
+ $variables = get_class_vars(get_class($mysqli));
+ foreach ($variables as $var => $v) {
+ if (isset($expected_class_variables[$var])) {
+ unset($expected_class_variables[$var]);
+ unset($variables[$var]);
+ }
+ }
+
+ if (!empty($expected_class_variables)) {
+ printf("Dumping list of missing class variables\n");
+ var_dump($expected_class_variables);
+ }
+ if (!empty($variables)) {
+ printf("Dumping list of unexpected class variables\n");
+ var_dump($variables);
+ }
+ echo "ok\n";
+
+ printf("\nObject variables:\n");
+ $variables = get_object_vars($mysqli);
+ foreach ($variables as $var => $v) {
+ if (isset($expected_object_variables[$var])) {
+ unset($expected_object_variables[$var]);
+ unset($variables[$var]);
+ }
+ }
+
+ if (!empty($expected_object_variables)) {
+ printf("Dumping list of missing object variables\n");
+ var_dump($expected_object_variables);
+ }
+ if (!empty($variables)) {
+ printf("Dumping list of unexpected object variables\n");
+ var_dump($variables);
+ }
+ echo "ok\n";
+
+
+ printf("\nMagic, magic properties:\n");
+
+ assert(mysqli_affected_rows($link) === $mysqli->affected_rows);
+ printf("mysqli->affected_rows = '%s'/%s ('%s'/%s)\n",
+ $mysqli->affected_rows, gettype($mysqli->affected_rows),
+ mysqli_affected_rows($link), gettype(mysqli_affected_rows($link)));
+
+ assert(mysqli_get_client_info() === $mysqli->client_info);
+ printf("mysqli->client_info = '%s'/%s ('%s'/%s)\n",
+ $mysqli->client_info, gettype($mysqli->client_info),
+ mysqli_get_client_info(), gettype(mysqli_get_client_info()));
+
+ assert(mysqli_get_client_version() === $mysqli->client_version);
+ printf("mysqli->client_version = '%s'/%s ('%s'/%s)\n",
+ $mysqli->client_version, gettype($mysqli->client_version),
+ mysqli_get_client_version(), gettype(mysqli_get_client_version()));
+
+ assert(mysqli_errno($link) === $mysqli->errno);
+ printf("mysqli->errno = '%s'/%s ('%s'/%s)\n",
+ $mysqli->errno, gettype($mysqli->errno),
+ mysqli_errno($link), gettype(mysqli_errno($link)));
+
+ assert(mysqli_error($link) === $mysqli->error);
+ printf("mysqli->error = '%s'/%s ('%s'/%s)\n",
+ $mysqli->error, gettype($mysqli->error),
+ mysqli_error($link), gettype(mysqli_error($link)));
+
+ if (version_compare(PHP_VERSION, '5.3.99', '>')) {
+ assert(mysqli_error_list($link) === $mysqli->error_list);
+ assert(is_array($mysqli->error_list));
+ }
+
+ assert(mysqli_field_count($link) === $mysqli->field_count);
+ printf("mysqli->field_count = '%s'/%s ('%s'/%s)\n",
+ $mysqli->field_count, gettype($mysqli->field_count),
+ mysqli_field_count($link), gettype(mysqli_field_count($link)));
+
+ assert(mysqli_insert_id($link) === $mysqli->insert_id);
+ printf("mysqli->insert_id = '%s'/%s ('%s'/%s)\n",
+ $mysqli->insert_id, gettype($mysqli->insert_id),
+ mysqli_insert_id($link), gettype(mysqli_insert_id($link)));
+
+ assert(mysqli_sqlstate($link) === $mysqli->sqlstate);
+ printf("mysqli->sqlstate = '%s'/%s ('%s'/%s)\n",
+ $mysqli->sqlstate, gettype($mysqli->sqlstate),
+ mysqli_sqlstate($link), gettype(mysqli_sqlstate($link)));
+
+ assert(soundex(mysqli_stat($link)) == soundex($mysqli->stat));
+ printf("mysqli->stat = '%s'/%s ('%s'/%s)\n",
+ $mysqli->stat, gettype($mysqli->stat),
+ mysqli_stat($link), gettype(mysqli_stat($link)));
+
+ assert(mysqli_get_host_info($link) === $mysqli->host_info);
+ printf("mysqli->host_info = '%s'/%s ('%s'/%s)\n",
+ $mysqli->host_info, gettype($mysqli->host_info),
+ mysqli_get_host_info($link), gettype(mysqli_get_host_info($link)));
+
+ /* note that the data types are different */
+ assert(mysqli_info($link) == $mysqli->info);
+ printf("mysqli->info = '%s'/%s ('%s'/%s)\n",
+ $mysqli->info, gettype($mysqli->info),
+ mysqli_info($link), gettype(mysqli_info($link)));
+
+ assert(mysqli_thread_id($link) > $mysqli->thread_id);
+ assert(gettype($mysqli->thread_id) == gettype(mysqli_thread_id($link)));
+ printf("mysqli->thread_id = '%s'/%s ('%s'/%s)\n",
+ $mysqli->thread_id, gettype($mysqli->thread_id),
+ mysqli_thread_id($link), gettype(mysqli_thread_id($link)));
+
+ assert(mysqli_get_proto_info($link) === $mysqli->protocol_version);
+ printf("mysqli->protocol_version = '%s'/%s ('%s'/%s)\n",
+ $mysqli->protocol_version, gettype($mysqli->protocol_version),
+ mysqli_get_proto_info($link), gettype(mysqli_get_proto_info($link)));
+
+ assert(mysqli_get_server_info($link) === $mysqli->server_info);
+ printf("mysqli->server_info = '%s'/%s ('%s'/%s)\n",
+ $mysqli->server_info, gettype($mysqli->server_info),
+ mysqli_get_server_info($link), gettype(mysqli_get_server_info($link)));
+
+ assert(mysqli_get_server_version($link) === $mysqli->server_version);
+ printf("mysqli->server_version = '%s'/%s ('%s'/%s)\n",
+ $mysqli->server_version, gettype($mysqli->server_version),
+ mysqli_get_server_version($link), gettype(mysqli_get_server_version($link)));
+
+ assert(mysqli_warning_count($link) === $mysqli->warning_count);
+ printf("mysqli->warning_count = '%s'/%s ('%s'/%s)\n",
+ $mysqli->warning_count, gettype($mysqli->warning_count),
+ mysqli_warning_count($link), gettype(mysqli_warning_count($link)));
+
+ printf("\nAccess to undefined properties:\n");
+ printf("mysqli->unknown = '%s'\n", @$mysqli->unknown);
+
+ @$mysqli->unknown = 13;
+ printf("setting mysqli->unknown, mysqli_unknown = '%s'\n", @$mysqli->unknown);
+
+ $unknown = 'friday';
+ @$mysqli->unknown = $unknown;
+ printf("setting mysqli->unknown, mysqli_unknown = '%s'\n", @$mysqli->unknown);
+
+ $mysqli = new my_mysqli($host, $user, $passwd, $db, $port, $socket);
+ printf("\nAccess hidden properties for MYSLQI_STATUS_INITIALIZED (TODO documentation):\n");
+ assert(mysqli_connect_error() === $mysqli->connect_error);
+ printf("mysqli->connect_error = '%s'/%s ('%s'/%s)\n",
+ $mysqli->connect_error, gettype($mysqli->connect_error),
+ mysqli_connect_error(), gettype(mysqli_connect_error()));
+
+ assert(mysqli_connect_errno() === $mysqli->connect_errno);
+ printf("mysqli->connect_errno = '%s'/%s ('%s'/%s)\n",
+ $mysqli->connect_errno, gettype($mysqli->connect_errno),
+ mysqli_connect_errno(), gettype(mysqli_connect_errno()));
+
+ print "done!";
+?>
+--EXPECTF--
+Parent class:
+bool(false)
+
+Methods:
+ok
+
+Class variables:
+ok
+
+Object variables:
+ok
+
+Magic, magic properties:
+mysqli->affected_rows = '%s'/integer ('%s'/integer)
+mysqli->client_info = '%s'/%unicode|string% ('%s'/%unicode|string%)
+mysqli->client_version = '%d'/integer ('%d'/integer)
+mysqli->errno = '0'/integer ('0'/integer)
+mysqli->error = ''/%unicode|string% (''/%unicode|string%)
+mysqli->field_count = '0'/integer ('0'/integer)
+mysqli->insert_id = '0'/integer ('0'/integer)
+mysqli->sqlstate = '00000'/%unicode|string% ('00000'/%unicode|string%)
+mysqli->stat = 'Uptime: %d Threads: %d Questions: %d Slow queries: %d Opens: %d Flush tables: %d Open tables: %d Queries per second avg: %d.%d'/string ('Uptime: %d Threads: %d Questions: %d Slow queries: %d Opens: %d Flush tables: %d Open tables: %d Queries per second avg: %d.%d'/string)
+mysqli->host_info = '%s'/%unicode|string% ('%s'/%unicode|string%)
+mysqli->info = ''/NULL (''/%unicode|string%)
+mysqli->thread_id = '%d'/integer ('%d'/integer)
+mysqli->protocol_version = '%d'/integer ('%d'/integer)
+mysqli->server_info = '%s'/%unicode|string% ('%s'/%unicode|string%)
+mysqli->server_version = '%d'/integer ('%d'/integer)
+mysqli->warning_count = '0'/integer ('0'/integer)
+
+Access to undefined properties:
+mysqli->unknown = ''
+setting mysqli->unknown, mysqli_unknown = '13'
+setting mysqli->unknown, mysqli_unknown = 'friday'
+
+Access hidden properties for MYSLQI_STATUS_INITIALIZED (TODO documentation):
+mysqli->connect_error = ''/NULL (''/NULL)
+mysqli->connect_errno = '0'/integer ('0'/integer)
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_class_mysqli_properties_no_conn.phpt b/ext/mysqli/tests/mysqli_class_mysqli_properties_no_conn.phpt
new file mode 100644
index 0000000..e4d0b08
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_class_mysqli_properties_no_conn.phpt
@@ -0,0 +1,290 @@
+--TEST--
+Interface of the class mysqli
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require('table.inc');
+
+ function dump_properties($mysqli) {
+
+ printf("\nClass variables:\n");
+ $variables = array_keys(get_class_vars(get_class($mysqli)));
+ sort($variables);
+ foreach ($variables as $k => $var) {
+ printf("%s = '%s'\n", $var, var_export(@$mysqli->$var, true));
+ }
+
+ printf("\nObject variables:\n");
+ $variables = array_keys(get_object_vars($mysqli));
+ foreach ($variables as $k => $var) {
+ printf("%s = '%s'\n", $var, var_export(@$mysqli->$var, true));
+ }
+
+ printf("\nMagic, magic properties:\n");
+
+ assert(@mysqli_affected_rows($mysqli) === @$mysqli->affected_rows);
+ printf("mysqli->affected_rows = '%s'/%s ('%s'/%s)\n",
+ @$mysqli->affected_rows, gettype(@$mysqli->affected_rows),
+ @mysqli_affected_rows($mysqli), gettype(@mysqli_affected_rows($mysqli)));
+
+ assert(@mysqli_get_client_info() === @$mysqli->client_info);
+ printf("mysqli->client_info = '%s'/%s ('%s'/%s)\n",
+ @$mysqli->client_info, gettype(@$mysqli->client_info),
+ @mysqli_get_client_info(), gettype(@mysqli_get_client_info()));
+
+ assert(@mysqli_get_client_version() === @$mysqli->client_version);
+ printf("mysqli->client_version = '%s'/%s ('%s'/%s)\n",
+ @$mysqli->client_version, gettype(@$mysqli->client_version),
+ @mysqli_get_client_version(), gettype(@mysqli_get_client_version()));
+
+ assert(@mysqli_errno($mysqli) === @$mysqli->errno);
+ printf("mysqli->errno = '%s'/%s ('%s'/%s)\n",
+ @$mysqli->errno, gettype(@$mysqli->errno),
+
+ @mysqli_errno($mysqli), gettype(@mysqli_errno($mysqli)));
+
+ assert(@mysqli_error($mysqli) === @$mysqli->error);
+ printf("mysqli->error = '%s'/%s ('%s'/%s)\n",
+ @$mysqli->error, gettype(@$mysqli->error),
+ @mysqli_error($mysqli), gettype(@mysqli_error($mysqli)));
+
+ assert(@mysqli_field_count($mysqli) === @$mysqli->field_count);
+ printf("mysqli->field_count = '%s'/%s ('%s'/%s)\n",
+ @$mysqli->field_count, gettype(@$mysqli->field_count),
+ @mysqli_field_count($mysqli), gettype(@mysqli_field_count($mysqli)));
+
+ assert(@mysqli_insert_id($mysqli) === @$mysqli->insert_id);
+ printf("mysqli->insert_id = '%s'/%s ('%s'/%s)\n",
+ @$mysqli->insert_id, gettype(@$mysqli->insert_id),
+ @mysqli_insert_id($mysqli), gettype(@mysqli_insert_id($mysqli)));
+
+ assert(@mysqli_sqlstate($mysqli) === @$mysqli->sqlstate);
+ printf("mysqli->sqlstate = '%s'/%s ('%s'/%s)\n",
+ @$mysqli->sqlstate, gettype(@$mysqli->sqlstate),
+ @mysqli_sqlstate($mysqli), gettype(@mysqli_sqlstate($mysqli)));
+
+ assert(@mysqli_get_host_info($mysqli) === @$mysqli->host_info);
+ printf("mysqli->host_info = '%s'/%s ('%s'/%s)\n",
+ @$mysqli->host_info, gettype(@$mysqli->host_info),
+ @mysqli_get_host_info($mysqli), gettype(@mysqli_get_host_info($mysqli)));
+
+ /* note that the data types are different */
+ assert(@mysqli_info($mysqli) == @$mysqli->info);
+ printf("mysqli->info = '%s'/%s ('%s'/%s)\n",
+ @$mysqli->info, gettype(@$mysqli->info),
+ @mysqli_info($mysqli), gettype(@mysqli_info($mysqli)));
+
+ assert(@mysqli_thread_id($mysqli) > @$mysqli->thread_id);
+ assert(gettype(@$mysqli->thread_id) == gettype(@mysqli_thread_id($mysqli)));
+ printf("mysqli->thread_id = '%s'/%s ('%s'/%s)\n",
+ @$mysqli->thread_id, gettype(@$mysqli->thread_id),
+ @mysqli_thread_id($mysqli), gettype(@mysqli_thread_id($mysqli)));
+
+ assert(@mysqli_get_proto_info($mysqli) === @$mysqli->protocol_version);
+ printf("mysqli->protocol_version = '%s'/%s ('%s'/%s)\n",
+ @$mysqli->protocol_version, gettype(@$mysqli->protocol_version),
+ @mysqli_get_proto_info($mysqli), gettype(@mysqli_get_proto_info($mysqli)));
+
+ assert(@mysqli_get_server_info($mysqli) === @$mysqli->server_info);
+ printf("mysqli->server_info = '%s'/%s ('%s'/%s)\n",
+ @$mysqli->server_info, gettype(@$mysqli->server_info),
+ @mysqli_get_server_info($mysqli), gettype(@mysqli_get_server_info($mysqli)));
+
+ assert(@mysqli_get_server_version($mysqli) === @$mysqli->server_version);
+ printf("mysqli->server_version = '%s'/%s ('%s'/%s)\n",
+ @$mysqli->server_version, gettype(@$mysqli->server_version),
+ @mysqli_get_server_version($mysqli), gettype(@mysqli_get_server_version($mysqli)));
+
+ assert(@mysqli_warning_count($mysqli) === @$mysqli->warning_count);
+ printf("mysqli->warning_count = '%s'/%s ('%s'/%s)\n",
+ @$mysqli->warning_count, gettype(@$mysqli->warning_count),
+ @mysqli_warning_count($mysqli), gettype(@mysqli_warning_count($mysqli)));
+
+ printf("\nAccess to undefined properties:\n");
+ printf("mysqli->unknown = '%s'\n", @$mysqli->unknown);
+
+ @$mysqli->unknown = 13;
+ printf("setting mysqli->unknown, @mysqli_unknown = '%s'\n", @$mysqli->unknown);
+
+ $unknown = 'friday';
+ @$mysqli->unknown = $unknown;
+ printf("setting mysqli->unknown, @mysqli_unknown = '%s'\n", @$mysqli->unknown);
+
+ printf("\nAccess hidden properties for MYSLQI_STATUS_INITIALIZED (TODO documentation):\n");
+ assert(@mysqli_connect_error() === @$mysqli->connect_error);
+ printf("mysqli->connect_error = '%s'/%s ('%s'/%s)\n",
+ @$mysqli->connect_error, gettype(@$mysqli->connect_error),
+ @mysqli_connect_error(), gettype(@mysqli_connect_error()));
+
+ assert(@mysqli_connect_errno() === @$mysqli->connect_errno);
+ printf("mysqli->connect_errno = '%s'/%s ('%s'/%s)\n",
+ @$mysqli->connect_errno, gettype(@$mysqli->connect_errno),
+ @mysqli_connect_errno(), gettype(@mysqli_connect_errno()));
+ }
+
+ printf("Without RS\n");
+ $mysqli = @new mysqli($host, $user, $passwd . "invalid", $db, $port, $socket);
+ dump_properties($mysqli);
+
+ printf("With RS\n");
+ $mysqli = @new mysqli($host, $user, $passwd . "invalid", $db, $port, $socket);
+ $res = @$mysqli->query("SELECT * FROM test");
+ dump_properties($mysqli);
+
+ print "done!";
+?>
+--CLEAN--
+<?php require_once("clean_table.inc"); ?>
+--EXPECTF--
+Without RS
+
+Class variables:
+affected_rows = 'NULL'
+client_info = 'NULL'
+client_version = '%s'
+connect_errno = '%s'
+connect_error = ''%s'
+errno = 'NULL'
+error = 'NULL'
+error_list = 'NULL'
+field_count = 'NULL'
+host_info = 'NULL'
+info = 'NULL'
+insert_id = 'NULL'
+protocol_version = 'NULL'
+server_info = 'NULL'
+server_version = 'NULL'
+sqlstate = 'NULL'
+stat = 'NULL'
+thread_id = 'NULL'
+warning_count = 'NULL'
+
+Object variables:
+affected_rows = 'NULL'
+client_info = 'NULL'
+client_version = '%s'
+connect_errno = '%s'
+connect_error = '%s'
+errno = 'NULL'
+error = 'NULL'
+error_list = 'NULL'
+field_count = 'NULL'
+host_info = 'NULL'
+info = 'NULL'
+insert_id = 'NULL'
+server_info = 'NULL'
+server_version = 'NULL'
+stat = 'NULL'
+sqlstate = 'NULL'
+protocol_version = 'NULL'
+thread_id = 'NULL'
+warning_count = 'NULL'
+
+Magic, magic properties:
+mysqli->affected_rows = ''/NULL (''/NULL)
+
+Warning: assert(): Assertion failed in %s on line %d
+mysqli->client_info = ''/NULL ('%s'/%s)
+mysqli->client_version = '%s'/integer ('%s'/integer)
+mysqli->errno = ''/NULL (''/NULL)
+mysqli->error = ''/NULL (''/NULL)
+mysqli->field_count = ''/NULL (''/NULL)
+mysqli->insert_id = ''/NULL (''/NULL)
+mysqli->sqlstate = ''/NULL (''/NULL)
+mysqli->host_info = ''/NULL (''/NULL)
+mysqli->info = ''/NULL (''/NULL)
+
+Warning: assert(): Assertion failed in %s on line %d
+mysqli->thread_id = ''/NULL (''/NULL)
+mysqli->protocol_version = ''/NULL (''/NULL)
+mysqli->server_info = ''/NULL (''/NULL)
+mysqli->server_version = ''/NULL (''/NULL)
+mysqli->warning_count = ''/NULL (''/NULL)
+
+Access to undefined properties:
+mysqli->unknown = ''
+setting mysqli->unknown, @mysqli_unknown = '13'
+setting mysqli->unknown, @mysqli_unknown = 'friday'
+
+Access hidden properties for MYSLQI_STATUS_INITIALIZED (TODO documentation):
+mysqli->connect_error = '%s'/%s)
+mysqli->connect_errno = '%s'/integer ('%s'/integer)
+With RS
+
+Class variables:
+affected_rows = 'NULL'
+client_info = 'NULL'
+client_version = '%s'
+connect_errno = '%s'
+connect_error = '%s'
+errno = 'NULL'
+error = 'NULL'
+error_list = 'NULL'
+field_count = 'NULL'
+host_info = 'NULL'
+info = 'NULL'
+insert_id = 'NULL'
+protocol_version = 'NULL'
+server_info = 'NULL'
+server_version = 'NULL'
+sqlstate = 'NULL'
+stat = 'NULL'
+thread_id = 'NULL'
+warning_count = 'NULL'
+
+Object variables:
+affected_rows = 'NULL'
+client_info = 'NULL'
+client_version = '%s'
+connect_errno = '%s'
+connect_error = '%s'
+errno = 'NULL'
+error = 'NULL'
+error_list = 'NULL'
+field_count = 'NULL'
+host_info = 'NULL'
+info = 'NULL'
+insert_id = 'NULL'
+server_info = 'NULL'
+server_version = 'NULL'
+stat = 'NULL'
+sqlstate = 'NULL'
+protocol_version = 'NULL'
+thread_id = 'NULL'
+warning_count = 'NULL'
+
+Magic, magic properties:
+mysqli->affected_rows = ''/NULL (''/NULL)
+
+Warning: assert(): Assertion failed in %s on line %d
+mysqli->client_info = ''/NULL ('%s'/%s)
+mysqli->client_version = '%s'/integer ('%s'/integer)
+mysqli->errno = ''/NULL (''/NULL)
+mysqli->error = ''/NULL (''/NULL)
+mysqli->field_count = ''/NULL (''/NULL)
+mysqli->insert_id = ''/NULL (''/NULL)
+mysqli->sqlstate = ''/NULL (''/NULL)
+mysqli->host_info = ''/NULL (''/NULL)
+mysqli->info = ''/NULL (''/NULL)
+
+Warning: assert(): Assertion failed in %s on line %d
+mysqli->thread_id = ''/NULL (''/NULL)
+mysqli->protocol_version = ''/NULL (''/NULL)
+mysqli->server_info = ''/NULL (''/NULL)
+mysqli->server_version = ''/NULL (''/NULL)
+mysqli->warning_count = ''/NULL (''/NULL)
+
+Access to undefined properties:
+mysqli->unknown = ''
+setting mysqli->unknown, @mysqli_unknown = '13'
+setting mysqli->unknown, @mysqli_unknown = 'friday'
+
+Access hidden properties for MYSLQI_STATUS_INITIALIZED (TODO documentation):
+mysqli->connect_error = '%s'/%s)
+mysqli->connect_errno = '%s'/integer ('%s'/integer)
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_class_mysqli_reflection.phpt b/ext/mysqli/tests/mysqli_class_mysqli_reflection.phpt
new file mode 100644
index 0000000..5fd4b6f
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_class_mysqli_reflection.phpt
@@ -0,0 +1,1246 @@
+--TEST--
+Interface of the class mysqli - Reflection
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('connect.inc');
+
+if (($tmp = substr(PHP_VERSION, 0, strpos(PHP_VERSION, '.'))) && ($tmp < 5))
+ die("skip Reflection not available before PHP 5 (found PHP $tmp)");
+/*
+Let's not deal with cross-version issues in the EXPECTF/UEXPECTF.
+Most of the things which we test are covered by mysqli_class_*_interface.phpt.
+Those tests go into the details and are aimed to be a development tool, no more.
+*/
+if (!$IS_MYSQLND)
+ die("skip Test has been written for the latest version of mysqlnd only");
+if ($MYSQLND_VERSION < 50004)
+ die("skip Test requires mysqlnd Revision 5.0.4 or newer");
+
+?>
+--FILE--
+<?php
+ require_once('reflection_tools.inc');
+ $class = new ReflectionClass('mysqli');
+ inspectClass($class);
+ print "done!\n";
+?>
+--EXPECTF--
+Inspecting class 'mysqli'
+isInternal: yes
+isUserDefined: no
+isInstantiable: yes
+isInterface: no
+isAbstract: no
+isFinal: no
+isIteratable: no
+Modifiers: '0'
+Parent Class: ''
+Extension: 'mysqli'
+
+Inspecting method 'mysqli'
+isFinal: no
+isAbstract: no
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isConstructor: yes
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: 8448
+Number of Parameters: 6
+Number of Required Parameters: 0
+
+Inspecting parameter 'host' of method 'mysqli'
+isArray: no
+allowsNull: no
+isPassedByReference: no
+isOptional: yes
+isDefaultValueAvailable: no
+
+Inspecting parameter 'user' of method 'mysqli'
+isArray: no
+allowsNull: no
+isPassedByReference: no
+isOptional: yes
+isDefaultValueAvailable: no
+
+Inspecting parameter 'password' of method 'mysqli'
+isArray: no
+allowsNull: no
+isPassedByReference: no
+isOptional: yes
+isDefaultValueAvailable: no
+
+Inspecting parameter 'database' of method 'mysqli'
+isArray: no
+allowsNull: no
+isPassedByReference: no
+isOptional: yes
+isDefaultValueAvailable: no
+
+Inspecting parameter 'port' of method 'mysqli'
+isArray: no
+allowsNull: no
+isPassedByReference: no
+isOptional: yes
+isDefaultValueAvailable: no
+
+Inspecting parameter 'socket' of method 'mysqli'
+isArray: no
+allowsNull: no
+isPassedByReference: no
+isOptional: yes
+isDefaultValueAvailable: no
+
+Inspecting method 'autocommit'
+isFinal: no
+isAbstract: no
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isConstructor: no
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: 256
+Number of Parameters: 1
+Number of Required Parameters: 1
+
+Inspecting parameter 'mode' of method 'autocommit'
+isArray: no
+allowsNull: no
+isPassedByReference: no
+isOptional: no
+isDefaultValueAvailable: no
+
+Inspecting method 'change_user'
+isFinal: no
+isAbstract: no
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isConstructor: no
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: 256
+Number of Parameters: 3
+Number of Required Parameters: 3
+
+Inspecting parameter 'user' of method 'change_user'
+isArray: no
+allowsNull: no
+isPassedByReference: no
+isOptional: no
+isDefaultValueAvailable: no
+
+Inspecting parameter 'password' of method 'change_user'
+isArray: no
+allowsNull: no
+isPassedByReference: no
+isOptional: no
+isDefaultValueAvailable: no
+
+Inspecting parameter 'database' of method 'change_user'
+isArray: no
+allowsNull: no
+isPassedByReference: no
+isOptional: no
+isDefaultValueAvailable: no
+
+Inspecting method 'character_set_name'
+isFinal: no
+isAbstract: no
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isConstructor: no
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: 256
+Number of Parameters: 0
+Number of Required Parameters: 0
+
+Inspecting method 'close'
+isFinal: no
+isAbstract: no
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isConstructor: no
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: 256
+Number of Parameters: 0
+Number of Required Parameters: 0
+
+Inspecting method 'commit'
+isFinal: no
+isAbstract: no
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isConstructor: no
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: 256
+Number of Parameters: 0
+Number of Required Parameters: 0
+
+Inspecting method 'connect'
+isFinal: no
+isAbstract: no
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isConstructor: no
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: 256
+Number of Parameters: 6
+Number of Required Parameters: 0
+
+Inspecting parameter 'host' of method 'connect'
+isArray: no
+allowsNull: no
+isPassedByReference: no
+isOptional: yes
+isDefaultValueAvailable: no
+
+Inspecting parameter 'user' of method 'connect'
+isArray: no
+allowsNull: no
+isPassedByReference: no
+isOptional: yes
+isDefaultValueAvailable: no
+
+Inspecting parameter 'password' of method 'connect'
+isArray: no
+allowsNull: no
+isPassedByReference: no
+isOptional: yes
+isDefaultValueAvailable: no
+
+Inspecting parameter 'database' of method 'connect'
+isArray: no
+allowsNull: no
+isPassedByReference: no
+isOptional: yes
+isDefaultValueAvailable: no
+
+Inspecting parameter 'port' of method 'connect'
+isArray: no
+allowsNull: no
+isPassedByReference: no
+isOptional: yes
+isDefaultValueAvailable: no
+
+Inspecting parameter 'socket' of method 'connect'
+isArray: no
+allowsNull: no
+isPassedByReference: no
+isOptional: yes
+isDefaultValueAvailable: no
+
+Inspecting method 'debug'
+isFinal: no
+isAbstract: no
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isConstructor: no
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: 256
+Number of Parameters: 1
+Number of Required Parameters: 1
+
+Inspecting parameter 'debug_options' of method 'debug'
+isArray: no
+allowsNull: no
+isPassedByReference: no
+isOptional: no
+isDefaultValueAvailable: no
+
+Inspecting method 'dump_debug_info'
+isFinal: no
+isAbstract: no
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isConstructor: no
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: 256
+Number of Parameters: 0
+Number of Required Parameters: 0
+
+Inspecting method 'escape_string'
+isFinal: no
+isAbstract: no
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isConstructor: no
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: 256
+Number of Parameters: 1
+Number of Required Parameters: 1
+
+Inspecting parameter 'string_to_escape' of method 'escape_string'
+isArray: no
+allowsNull: no
+isPassedByReference: no
+isOptional: no
+isDefaultValueAvailable: no
+
+Inspecting method 'get_charset'
+isFinal: no
+isAbstract: no
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isConstructor: no
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: 256
+Number of Parameters: 0
+Number of Required Parameters: 0
+
+Inspecting method 'get_client_info'
+isFinal: no
+isAbstract: no
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isConstructor: no
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: 256
+Number of Parameters: 0
+Number of Required Parameters: 0
+
+Inspecting method 'get_connection_stats'
+isFinal: no
+isAbstract: no
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isConstructor: no
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: 256
+Number of Parameters: 0
+Number of Required Parameters: 0
+
+Inspecting method 'get_server_info'
+isFinal: no
+isAbstract: no
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isConstructor: no
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: 256
+Number of Parameters: 0
+Number of Required Parameters: 0
+
+Inspecting method 'get_warnings'
+isFinal: no
+isAbstract: no
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isConstructor: no
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: 256
+Number of Parameters: 0
+Number of Required Parameters: 0
+
+Inspecting method 'init'
+isFinal: no
+isAbstract: no
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isConstructor: no
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: 256
+Number of Parameters: 0
+Number of Required Parameters: 0
+
+Inspecting method 'kill'
+isFinal: no
+isAbstract: no
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isConstructor: no
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: 256
+Number of Parameters: 1
+Number of Required Parameters: 1
+
+Inspecting parameter 'connection_id' of method 'kill'
+isArray: no
+allowsNull: no
+isPassedByReference: no
+isOptional: no
+isDefaultValueAvailable: no
+
+Inspecting method 'more_results'
+isFinal: no
+isAbstract: no
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isConstructor: no
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: 256
+Number of Parameters: 0
+Number of Required Parameters: 0
+
+Inspecting method 'multi_query'
+isFinal: no
+isAbstract: no
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isConstructor: no
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: 256
+Number of Parameters: 1
+Number of Required Parameters: 1
+
+Inspecting parameter 'query' of method 'multi_query'
+isArray: no
+allowsNull: no
+isPassedByReference: no
+isOptional: no
+isDefaultValueAvailable: no
+
+Inspecting method 'mysqli'
+isFinal: no
+isAbstract: no
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isConstructor: yes
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: 8448
+Number of Parameters: 6
+Number of Required Parameters: 0
+
+Inspecting parameter 'host' of method 'mysqli'
+isArray: no
+allowsNull: no
+isPassedByReference: no
+isOptional: yes
+isDefaultValueAvailable: no
+
+Inspecting parameter 'user' of method 'mysqli'
+isArray: no
+allowsNull: no
+isPassedByReference: no
+isOptional: yes
+isDefaultValueAvailable: no
+
+Inspecting parameter 'password' of method 'mysqli'
+isArray: no
+allowsNull: no
+isPassedByReference: no
+isOptional: yes
+isDefaultValueAvailable: no
+
+Inspecting parameter 'database' of method 'mysqli'
+isArray: no
+allowsNull: no
+isPassedByReference: no
+isOptional: yes
+isDefaultValueAvailable: no
+
+Inspecting parameter 'port' of method 'mysqli'
+isArray: no
+allowsNull: no
+isPassedByReference: no
+isOptional: yes
+isDefaultValueAvailable: no
+
+Inspecting parameter 'socket' of method 'mysqli'
+isArray: no
+allowsNull: no
+isPassedByReference: no
+isOptional: yes
+isDefaultValueAvailable: no
+
+Inspecting method 'next_result'
+isFinal: no
+isAbstract: no
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isConstructor: no
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: 256
+Number of Parameters: 0
+Number of Required Parameters: 0
+
+Inspecting method 'options'
+isFinal: no
+isAbstract: no
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isConstructor: no
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: 256
+Number of Parameters: 2
+Number of Required Parameters: 2
+
+Inspecting parameter 'option' of method 'options'
+isArray: no
+allowsNull: no
+isPassedByReference: no
+isOptional: no
+isDefaultValueAvailable: no
+
+Inspecting parameter 'value' of method 'options'
+isArray: no
+allowsNull: no
+isPassedByReference: no
+isOptional: no
+isDefaultValueAvailable: no
+
+Inspecting method 'ping'
+isFinal: no
+isAbstract: no
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isConstructor: no
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: 256
+Number of Parameters: 0
+Number of Required Parameters: 0
+
+Inspecting method 'poll'
+isFinal: no
+isAbstract: no
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: yes
+isConstructor: no
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: 257
+Number of Parameters: 5
+Number of Required Parameters: 4
+
+Inspecting parameter 'read' of method 'poll'
+isArray: yes
+allowsNull: yes
+isPassedByReference: yes
+isOptional: no
+isDefaultValueAvailable: no
+
+Inspecting parameter 'write' of method 'poll'
+isArray: yes
+allowsNull: yes
+isPassedByReference: yes
+isOptional: no
+isDefaultValueAvailable: no
+
+Inspecting parameter 'error' of method 'poll'
+isArray: yes
+allowsNull: yes
+isPassedByReference: yes
+isOptional: no
+isDefaultValueAvailable: no
+
+Inspecting parameter 'sec' of method 'poll'
+isArray: no
+allowsNull: no
+isPassedByReference: no
+isOptional: no
+isDefaultValueAvailable: no
+
+Inspecting parameter 'usec' of method 'poll'
+isArray: no
+allowsNull: no
+isPassedByReference: no
+isOptional: yes
+isDefaultValueAvailable: no
+
+Inspecting method 'prepare'
+isFinal: no
+isAbstract: no
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isConstructor: no
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: 256
+Number of Parameters: 1
+Number of Required Parameters: 1
+
+Inspecting parameter 'query' of method 'prepare'
+isArray: no
+allowsNull: no
+isPassedByReference: no
+isOptional: no
+isDefaultValueAvailable: no
+
+Inspecting method 'query'
+isFinal: no
+isAbstract: no
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isConstructor: no
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: 256
+Number of Parameters: 1
+Number of Required Parameters: 1
+
+Inspecting parameter 'query' of method 'query'
+isArray: no
+allowsNull: no
+isPassedByReference: no
+isOptional: no
+isDefaultValueAvailable: no
+
+Inspecting method 'real_connect'
+isFinal: no
+isAbstract: no
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isConstructor: no
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: 256
+Number of Parameters: 7
+Number of Required Parameters: 0
+
+Inspecting parameter 'host' of method 'real_connect'
+isArray: no
+allowsNull: no
+isPassedByReference: no
+isOptional: yes
+isDefaultValueAvailable: no
+
+Inspecting parameter 'user' of method 'real_connect'
+isArray: no
+allowsNull: no
+isPassedByReference: no
+isOptional: yes
+isDefaultValueAvailable: no
+
+Inspecting parameter 'password' of method 'real_connect'
+isArray: no
+allowsNull: no
+isPassedByReference: no
+isOptional: yes
+isDefaultValueAvailable: no
+
+Inspecting parameter 'database' of method 'real_connect'
+isArray: no
+allowsNull: no
+isPassedByReference: no
+isOptional: yes
+isDefaultValueAvailable: no
+
+Inspecting parameter 'port' of method 'real_connect'
+isArray: no
+allowsNull: no
+isPassedByReference: no
+isOptional: yes
+isDefaultValueAvailable: no
+
+Inspecting parameter 'socket' of method 'real_connect'
+isArray: no
+allowsNull: no
+isPassedByReference: no
+isOptional: yes
+isDefaultValueAvailable: no
+
+Inspecting parameter 'flags' of method 'real_connect'
+isArray: no
+allowsNull: no
+isPassedByReference: no
+isOptional: yes
+isDefaultValueAvailable: no
+
+Inspecting method 'real_escape_string'
+isFinal: no
+isAbstract: no
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isConstructor: no
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: 256
+Number of Parameters: 1
+Number of Required Parameters: 1
+
+Inspecting parameter 'string_to_escape' of method 'real_escape_string'
+isArray: no
+allowsNull: no
+isPassedByReference: no
+isOptional: no
+isDefaultValueAvailable: no
+
+Inspecting method 'real_query'
+isFinal: no
+isAbstract: no
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isConstructor: no
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: 256
+Number of Parameters: 1
+Number of Required Parameters: 1
+
+Inspecting parameter 'query' of method 'real_query'
+isArray: no
+allowsNull: no
+isPassedByReference: no
+isOptional: no
+isDefaultValueAvailable: no
+
+Inspecting method 'reap_async_query'
+isFinal: no
+isAbstract: no
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isConstructor: no
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: 256
+Number of Parameters: 0
+Number of Required Parameters: 0
+
+Inspecting method 'refresh'
+isFinal: no
+isAbstract: no
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isConstructor: no
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: 256
+Number of Parameters: 1
+Number of Required Parameters: 1
+
+Inspecting parameter 'options' of method 'refresh'
+isArray: no
+allowsNull: no
+isPassedByReference: no
+isOptional: no
+isDefaultValueAvailable: no
+
+Inspecting method 'rollback'
+isFinal: no
+isAbstract: no
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isConstructor: no
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: 256
+Number of Parameters: 0
+Number of Required Parameters: 0
+
+Inspecting method 'select_db'
+isFinal: no
+isAbstract: no
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isConstructor: no
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: 256
+Number of Parameters: 1
+Number of Required Parameters: 1
+
+Inspecting parameter 'database' of method 'select_db'
+isArray: no
+allowsNull: no
+isPassedByReference: no
+isOptional: no
+isDefaultValueAvailable: no
+
+Inspecting method 'set_charset'
+isFinal: no
+isAbstract: no
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isConstructor: no
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: 256
+Number of Parameters: 1
+Number of Required Parameters: 1
+
+Inspecting parameter 'charset' of method 'set_charset'
+isArray: no
+allowsNull: no
+isPassedByReference: no
+isOptional: no
+isDefaultValueAvailable: no
+
+Inspecting method 'set_opt'
+isFinal: no
+isAbstract: no
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isConstructor: no
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: 256
+Number of Parameters: 2
+Number of Required Parameters: 2
+
+Inspecting parameter 'option' of method 'set_opt'
+isArray: no
+allowsNull: no
+isPassedByReference: no
+isOptional: no
+isDefaultValueAvailable: no
+
+Inspecting parameter 'value' of method 'set_opt'
+isArray: no
+allowsNull: no
+isPassedByReference: no
+isOptional: no
+isDefaultValueAvailable: no
+
+Inspecting method 'ssl_set'
+isFinal: no
+isAbstract: no
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isConstructor: no
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: 256
+Number of Parameters: 5
+Number of Required Parameters: 5
+
+Inspecting parameter 'key' of method 'ssl_set'
+isArray: no
+allowsNull: no
+isPassedByReference: no
+isOptional: no
+isDefaultValueAvailable: no
+
+Inspecting parameter 'cert' of method 'ssl_set'
+isArray: no
+allowsNull: no
+isPassedByReference: no
+isOptional: no
+isDefaultValueAvailable: no
+
+Inspecting parameter 'certificate_authority' of method 'ssl_set'
+isArray: no
+allowsNull: no
+isPassedByReference: no
+isOptional: no
+isDefaultValueAvailable: no
+
+Inspecting parameter 'certificate_authority_path' of method 'ssl_set'
+isArray: no
+allowsNull: no
+isPassedByReference: no
+isOptional: no
+isDefaultValueAvailable: no
+
+Inspecting parameter 'cipher' of method 'ssl_set'
+isArray: no
+allowsNull: no
+isPassedByReference: no
+isOptional: no
+isDefaultValueAvailable: no
+
+Inspecting method 'stat'
+isFinal: no
+isAbstract: no
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isConstructor: no
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: 256
+Number of Parameters: 0
+Number of Required Parameters: 0
+
+Inspecting method 'stmt_init'
+isFinal: no
+isAbstract: no
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isConstructor: no
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: 256
+Number of Parameters: 0
+Number of Required Parameters: 0
+
+Inspecting method 'store_result'
+isFinal: no
+isAbstract: no
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isConstructor: no
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: 256
+Number of Parameters: 0
+Number of Required Parameters: 0
+
+Inspecting method 'thread_safe'
+isFinal: no
+isAbstract: no
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isConstructor: no
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: 256
+Number of Parameters: 0
+Number of Required Parameters: 0
+
+Inspecting method 'use_result'
+isFinal: no
+isAbstract: no
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isConstructor: no
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: 256
+Number of Parameters: 0
+Number of Required Parameters: 0
+
+Inspecting property 'affected_rows'
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isDefault: yes
+Modifiers: 256
+
+Inspecting property 'client_info'
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isDefault: yes
+Modifiers: 256
+
+Inspecting property 'client_version'
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isDefault: yes
+Modifiers: 256
+
+Inspecting property 'connect_errno'
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isDefault: yes
+Modifiers: 256
+
+Inspecting property 'connect_error'
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isDefault: yes
+Modifiers: 256
+
+Inspecting property 'errno'
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isDefault: yes
+Modifiers: 256
+
+Inspecting property 'error'
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isDefault: yes
+Modifiers: 256
+
+Inspecting property 'error_list'
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isDefault: yes
+Modifiers: 256
+
+Inspecting property 'field_count'
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isDefault: yes
+Modifiers: 256
+
+Inspecting property 'host_info'
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isDefault: yes
+Modifiers: 256
+
+Inspecting property 'info'
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isDefault: yes
+Modifiers: 256
+
+Inspecting property 'insert_id'
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isDefault: yes
+Modifiers: 256
+
+Inspecting property 'protocol_version'
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isDefault: yes
+Modifiers: 256
+
+Inspecting property 'server_info'
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isDefault: yes
+Modifiers: 256
+
+Inspecting property 'server_version'
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isDefault: yes
+Modifiers: 256
+
+Inspecting property 'sqlstate'
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isDefault: yes
+Modifiers: 256
+
+Inspecting property 'stat'
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isDefault: yes
+Modifiers: 256
+
+Inspecting property 'thread_id'
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isDefault: yes
+Modifiers: 256
+
+Inspecting property 'warning_count'
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isDefault: yes
+Modifiers: 256
+Default property 'affected_rows'
+Default property 'client_info'
+Default property 'client_version'
+Default property 'connect_errno'
+Default property 'connect_error'
+Default property 'errno'
+Default property 'error'
+Default property 'error_list'
+Default property 'field_count'
+Default property 'host_info'
+Default property 'info'
+Default property 'insert_id'
+Default property 'protocol_version'
+Default property 'server_info'
+Default property 'server_version'
+Default property 'sqlstate'
+Default property 'stat'
+Default property 'thread_id'
+Default property 'warning_count'
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_class_mysqli_result_interface.phpt b/ext/mysqli/tests/mysqli_class_mysqli_result_interface.phpt
new file mode 100644
index 0000000..b327fe6
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_class_mysqli_result_interface.phpt
@@ -0,0 +1,193 @@
+--TEST--
+Interface of the class mysqli_result
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require('connect.inc');
+ require('table.inc');
+
+ $mysqli = new my_mysqli($host, $user, $passwd, $db, $port, $socket);
+ $mysqli_result = $mysqli->query('SELECT * FROM test');
+ $row = $mysqli_result->fetch_row();
+
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+ $res = mysqli_query($link, 'SELECT * FROM test');
+ assert(mysqli_fetch_row($res) === $row);
+
+ printf("Parent class:\n");
+ var_dump(get_parent_class($mysqli_result));
+
+ printf("\nMethods:\n");
+ $methods = get_class_methods($mysqli_result);
+ $expected_methods = array(
+ '__construct' => true,
+ 'close' => true,
+ 'data_seek' => true,
+ 'fetch_array' => true,
+ 'fetch_assoc' => true,
+ 'fetch_field' => true,
+ 'fetch_field_direct' => true,
+ 'fetch_fields' => true,
+ 'fetch_object' => true,
+ 'fetch_row' => true,
+ 'field_seek' => true,
+ 'free' => true,
+ 'free_result' => true,
+ );
+ if ($IS_MYSQLND)
+ $expected_methods['fetch_all'] = true;
+
+ foreach ($methods as $k => $method) {
+ if (isset($expected_methods[$method])) {
+ unset($expected_methods[$method]);
+ unset($methods[$k]);
+ }
+ if ($method == 'mysqli_result') {
+ // get_class_method reports different constructor names
+ unset($expected_methods['__construct']);
+ unset($methods[$k]);
+ }
+ }
+
+ if (!empty($expected_methods)) {
+ printf("Dumping list of missing methods.\n");
+ var_dump($expected_methods);
+ }
+ if (!empty($methods)) {
+ printf("Dumping list of unexpected methods.\n");
+ var_dump($methods);
+ }
+ if (empty($expected_methods) && empty($methods))
+ printf("ok\n");
+
+
+ printf("\nClass variables:\n");
+ $variables = array_keys(get_class_vars(get_class($mysqli_result)));
+ sort($variables);
+ foreach ($variables as $k => $var)
+ printf("%s\n", $var);
+
+ printf("\nObject variables:\n");
+ $variables = array_keys(get_object_vars($mysqli_result));
+ foreach ($variables as $k => $var)
+ printf("%s\n", $var);
+
+ printf("\nMagic, magic properties:\n");
+
+ assert(($tmp = mysqli_field_tell($res)) === $mysqli_result->current_field);
+ printf("mysqli_result->current_field = '%s'/%s ('%s'/%s)\n",
+ $mysqli_result->current_field, gettype($mysqli_result->current_field),
+ $tmp, gettype($tmp));
+
+ assert(($tmp = mysqli_field_count($link)) === $mysqli_result->field_count);
+ printf("mysqli_result->field_count = '%s'/%s ('%s'/%s)\n",
+ $mysqli_result->field_count, gettype($mysqli_result->field_count),
+ $tmp, gettype($tmp));
+
+ assert(($tmp = mysqli_fetch_lengths($res)) === $mysqli_result->lengths);
+ printf("mysqli_result->lengths -> '%s'/%s ('%s'/%s)\n",
+ ((is_array($mysqli_result->lengths)) ? implode(' ', $mysqli_result->lengths) : 'n/a'),
+ gettype($mysqli_result->lengths),
+ ((is_array($tmp)) ? implode(' ', $tmp) : 'n/a'),
+ gettype($tmp));
+
+ assert(($tmp = mysqli_num_rows($res)) === $mysqli_result->num_rows);
+ printf("mysqli_result->num_rows = '%s'/%s ('%s'/%s)\n",
+ $mysqli_result->num_rows, gettype($mysqli_result->num_rows),
+ $tmp, gettype($tmp));
+
+ assert(in_array($mysqli_result->type, array(MYSQLI_STORE_RESULT, MYSQLI_USE_RESULT)));
+ printf("mysqli_result->type = '%s'/%s\n",
+ ((MYSQLI_STORE_RESULT == $mysqli_result->type) ? 'store' : 'use'),
+ gettype($mysqli_result->type));
+
+ printf("\nAccess to undefined properties:\n");
+ printf("mysqli_result->unknown = '%s'\n", @$mysqli_result->unknown);
+
+ printf("\nConstructor:\n");
+ if (!is_object($res = new mysqli_result($link)))
+ printf("[001] Expecting object/mysqli_result got %s/%s\n", gettye($res), $res);
+
+ if (null !== ($tmp = @$res->num_rows))
+ printf("[002] Expecting NULL got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_query($link, "SELECT id FROM test ORDER BY id"))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!is_object($res = new mysqli_result($link)))
+ printf("[004] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!is_object($res = new mysqli_result($link, MYSQLI_STORE_RESULT)))
+ printf("[005] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!is_object($res = new mysqli_result($link, MYSQLI_USE_RESULT)))
+ printf("[006] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!is_object($res = new mysqli_result($link, 'invalid')))
+ printf("[007] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $valid = array(MYSQLI_STORE_RESULT, MYSQLI_USE_RESULT);
+ do {
+ $mode = mt_rand(-1000, 1000);
+ } while (in_array($mode, $valid));
+
+ if ($TEST_EXPERIMENTAL) {
+ ob_start();
+ if (!is_object($res = new mysqli_result($link, $mode)))
+ printf("[008] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ $content = ob_get_contents();
+ ob_end_clean();
+ if (!stristr($content, 'Invalid value for resultmode'))
+ printf("[009] Expecting warning because of invalid resultmode\n");
+ }
+
+ if (!is_object($res = new mysqli_result('foo')))
+ printf("[010] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!is_object($res = @new mysqli_result($link, MYSQLI_STORE_RESULT, 1)))
+ printf("[011] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ print "done!";
+?>
+--EXPECTF--
+Parent class:
+bool(false)
+
+Methods:
+ok
+
+Class variables:
+current_field
+field_count
+lengths
+num_rows
+type
+
+Object variables:
+current_field
+field_count
+lengths
+num_rows
+type
+
+Magic, magic properties:
+mysqli_result->current_field = '0'/integer ('0'/integer)
+mysqli_result->field_count = '2'/integer ('2'/integer)
+mysqli_result->lengths -> '1 1'/array ('1 1'/array)
+mysqli_result->num_rows = '6'/integer ('6'/integer)
+mysqli_result->type = 'store'/integer
+
+Access to undefined properties:
+mysqli_result->unknown = ''
+
+Constructor:
+
+Warning: mysqli_result::__construct() expects parameter 2 to be long, %unicode_string_optional% given in %s on line %d
+
+Warning: mysqli_result::__construct() expects parameter 1 to be mysqli, %unicode_string_optional% given in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_class_mysqli_result_reflection.phpt b/ext/mysqli/tests/mysqli_class_mysqli_result_reflection.phpt
new file mode 100644
index 0000000..988b827
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_class_mysqli_result_reflection.phpt
@@ -0,0 +1,369 @@
+--TEST--
+Interface of the class mysqli_result - Reflection
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+require_once('connect.inc');
+
+if (($tmp = substr(PHP_VERSION, 0, strpos(PHP_VERSION, '.'))) && ($tmp < 5))
+ die("skip Reflection not available before PHP 5 (found PHP $tmp)");
+
+/*
+Let's not deal with cross-version issues in the EXPECTF/UEXPECTF.
+Most of the things which we test are covered by mysqli_class_*_interface.phpt.
+Those tests go into the details and are aimed to be a development tool, no more.
+*/
+if (!$IS_MYSQLND)
+ die("skip Test has been written for the latest version of mysqlnd only");
+if ($MYSQLND_VERSION < 50004)
+ die("skip Test requires mysqlnd Revision 5.0.4 or newer");
+?>
+--FILE--
+<?php
+ require_once('reflection_tools.inc');
+ $class = new ReflectionClass('mysqli_result');
+ inspectClass($class);
+ print "done!";
+?>
+--EXPECTF--
+Inspecting class 'mysqli_result'
+isInternal: yes
+isUserDefined: no
+isInstantiable: yes
+isInterface: no
+isAbstract: no
+isFinal: no
+isIteratable: yes
+Modifiers: '0'
+Parent Class: ''
+Extension: 'mysqli'
+
+Inspecting method '__construct'
+isFinal: no
+isAbstract: no
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isConstructor: yes
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: 8448
+Number of Parameters: 0
+Number of Required Parameters: 0
+
+Inspecting method '__construct'
+isFinal: no
+isAbstract: no
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isConstructor: yes
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: 8448
+Number of Parameters: 0
+Number of Required Parameters: 0
+
+Inspecting method 'close'
+isFinal: no
+isAbstract: no
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isConstructor: no
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: 256
+Number of Parameters: 0
+Number of Required Parameters: 0
+
+Inspecting method 'data_seek'
+isFinal: no
+isAbstract: no
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isConstructor: no
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: 256
+Number of Parameters: 1
+Number of Required Parameters: 1
+
+Inspecting parameter 'offset' of method 'data_seek'
+isArray: no
+allowsNull: no
+isPassedByReference: no
+isOptional: no
+isDefaultValueAvailable: no
+
+Inspecting method 'fetch_all'
+isFinal: no
+isAbstract: no
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isConstructor: no
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: 256
+Number of Parameters: 0
+Number of Required Parameters: 0
+
+Inspecting method 'fetch_array'
+isFinal: no
+isAbstract: no
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isConstructor: no
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: 256
+Number of Parameters: 1
+Number of Required Parameters: 0
+
+Inspecting parameter 'result_type' of method 'fetch_array'
+isArray: no
+allowsNull: no
+isPassedByReference: no
+isOptional: yes
+isDefaultValueAvailable: no
+
+Inspecting method 'fetch_assoc'
+isFinal: no
+isAbstract: no
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isConstructor: no
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: 256
+Number of Parameters: 0
+Number of Required Parameters: 0
+
+Inspecting method 'fetch_field'
+isFinal: no
+isAbstract: no
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isConstructor: no
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: 256
+Number of Parameters: 0
+Number of Required Parameters: 0
+
+Inspecting method 'fetch_field_direct'
+isFinal: no
+isAbstract: no
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isConstructor: no
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: 256
+Number of Parameters: 1
+Number of Required Parameters: 1
+
+Inspecting parameter 'field_nr' of method 'fetch_field_direct'
+isArray: no
+allowsNull: no
+isPassedByReference: no
+isOptional: no
+isDefaultValueAvailable: no
+
+Inspecting method 'fetch_fields'
+isFinal: no
+isAbstract: no
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isConstructor: no
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: 256
+Number of Parameters: 0
+Number of Required Parameters: 0
+
+Inspecting method 'fetch_object'
+isFinal: no
+isAbstract: no
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isConstructor: no
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: 256
+Number of Parameters: 2
+Number of Required Parameters: 0
+
+Inspecting parameter 'class_name' of method 'fetch_object'
+isArray: no
+allowsNull: no
+isPassedByReference: no
+isOptional: yes
+isDefaultValueAvailable: no
+
+Inspecting parameter 'params' of method 'fetch_object'
+isArray: yes
+allowsNull: no
+isPassedByReference: no
+isOptional: yes
+isDefaultValueAvailable: no
+
+Inspecting method 'fetch_row'
+isFinal: no
+isAbstract: no
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isConstructor: no
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: 256
+Number of Parameters: 0
+Number of Required Parameters: 0
+
+Inspecting method 'field_seek'
+isFinal: no
+isAbstract: no
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isConstructor: no
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: 256
+Number of Parameters: 1
+Number of Required Parameters: 1
+
+Inspecting parameter 'field_nr' of method 'field_seek'
+isArray: no
+allowsNull: no
+isPassedByReference: no
+isOptional: no
+isDefaultValueAvailable: no
+
+Inspecting method 'free'
+isFinal: no
+isAbstract: no
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isConstructor: no
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: 256
+Number of Parameters: 0
+Number of Required Parameters: 0
+
+Inspecting method 'free_result'
+isFinal: no
+isAbstract: no
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isConstructor: no
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: 256
+Number of Parameters: 0
+Number of Required Parameters: 0
+
+Inspecting property 'current_field'
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isDefault: yes
+Modifiers: 256
+
+Inspecting property 'field_count'
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isDefault: yes
+Modifiers: 256
+
+Inspecting property 'lengths'
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isDefault: yes
+Modifiers: 256
+
+Inspecting property 'num_rows'
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isDefault: yes
+Modifiers: 256
+
+Inspecting property 'type'
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isDefault: yes
+Modifiers: 256
+Default property 'current_field'
+Default property 'field_count'
+Default property 'lengths'
+Default property 'num_rows'
+Default property 'type'
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_class_mysqli_stmt_interface.phpt b/ext/mysqli/tests/mysqli_class_mysqli_stmt_interface.phpt
new file mode 100644
index 0000000..acf7379
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_class_mysqli_stmt_interface.phpt
@@ -0,0 +1,198 @@
+--TEST--
+Interface of the class mysqli_stmt
+--SKIPIF--
+<?php
+ require_once('skipif.inc');
+ require_once('skipifemb.inc');
+ require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require('connect.inc');
+ require('table.inc');
+
+ $link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+ $stmt = new mysqli_stmt($link);
+
+ printf("Parent class:\n");
+ var_dump(get_parent_class($stmt));
+
+ printf("\nMethods:\n");
+
+ $methods = get_class_methods($stmt);
+ $expected_methods = array(
+ '__construct' => true,
+ 'attr_get' => true,
+ 'attr_set' => true,
+ 'bind_param' => true,
+ 'bind_result' => true,
+ 'close' => true,
+ 'data_seek' => true,
+ 'execute' => true,
+ 'fetch' => true,
+ 'free_result' => true,
+ 'get_warnings' => true,
+ 'num_rows' => true,
+ 'prepare' => true,
+ 'reset' => true,
+ 'result_metadata' => true,
+ 'send_long_data' => true,
+ 'store_result' => true,
+ );
+
+ if ($IS_MYSQLND) {
+ $expected_methods['get_result'] = true;
+ $expected_methods['more_results'] = true;
+ $expected_methods['next_result'] = true;
+ }
+
+ foreach ($methods as $k => $method) {
+ if (isset($expected_methods[$method])) {
+ unset($methods[$k]);
+ unset($expected_methods[$method]);
+ }
+ if ($method == 'mysqli_stmt') {
+ // get_class_method reports different constructor names
+ unset($expected_methods['__construct']);
+ unset($methods[$k]);
+ }
+ }
+ if (!empty($methods)) {
+ printf("More methods found than indicated. Dumping list of unexpected methods.\n");
+ var_dump($methods);
+ }
+ if (!empty($expected_methods)) {
+ printf("Some methods are missing. Dumping list of missing methods.\n");
+ var_dump($expected_methods);
+ }
+ if (empty($methods) && empty($expected_methods))
+ printf("ok\n");
+
+ printf("\nClass variables:\n");
+ $variables = array_keys(get_class_vars(get_class($stmt)));
+ sort($variables);
+ foreach ($variables as $k => $var)
+ printf("%s\n", $var);
+
+ printf("\nObject variables:\n");
+ $variables = array_keys(get_object_vars($stmt));
+ foreach ($variables as $k => $var)
+ printf("%s\n", $var);
+
+printf("\nMagic, magic properties:\n");
+
+assert(mysqli_stmt_affected_rows($stmt) === $stmt->affected_rows);
+printf("stmt->affected_rows = '%s'\n", $stmt->affected_rows);
+
+if (!$stmt->prepare("INSERT INTO test(id, label) VALUES (100, 'z')") ||
+!$stmt->execute())
+printf("[001] [%d] %s\n", $stmt->errno, $stmt->error);
+
+assert(mysqli_stmt_affected_rows($stmt) === $stmt->affected_rows);
+printf("stmt->affected_rows = '%s'\n", $stmt->affected_rows);
+
+assert(mysqli_stmt_errno($stmt) === $stmt->errno);
+printf("stmt->errno = '%s'\n", $stmt->errno);
+
+assert(mysqli_stmt_error($stmt) === $stmt->error);
+printf("stmt->error = '%s'\n", $stmt->error);
+
+assert(mysqli_stmt_error_list($stmt) === $stmt->error_list);
+var_dump("stmt->error = ", $stmt->error_list);
+
+assert(mysqli_stmt_field_count($stmt) === $stmt->field_count);
+printf("stmt->field_count = '%s'\n", $stmt->field_count);
+
+assert($stmt->id > 0);
+printf("stmt->id = '%s'\n", $stmt->id);
+
+assert(mysqli_stmt_insert_id($stmt) === $stmt->insert_id);
+printf("stmt->insert_id = '%s'\n", $stmt->insert_id);
+
+assert(mysqli_stmt_num_rows($stmt) === $stmt->num_rows);
+printf("stmt->num_rows = '%s'\n", $stmt->num_rows);
+
+assert(mysqli_stmt_param_count($stmt) === $stmt->param_count);
+printf("stmt->param_count = '%s'\n", $stmt->param_count);
+
+assert(mysqli_stmt_sqlstate($stmt) === $stmt->sqlstate);
+printf("stmt->sqlstate = '%s'\n", $stmt->sqlstate);
+
+printf("\nAccess to undefined properties:\n");
+printf("stmt->unknown = '%s'\n", @$stmt->unknown);
+@$stmt->unknown = 13;
+printf("stmt->unknown = '%s'\n", @$stmt->unknown);
+
+printf("\nPrepare using the constructor:\n");
+$stmt = new mysqli_stmt($link, 'SELECT id FROM test ORDER BY id');
+if (!$stmt->execute())
+printf("[002] [%d] %s\n", $stmt->errno, $stmt->error);
+$stmt->close();
+
+$obj = new stdClass();
+if (!is_object($stmt = new mysqli_stmt($link, $obj)))
+printf("[003] Expecting NULL got %s/%s\n", gettype($stmt), $stmt);
+
+print "done!";
+?>
+--EXPECTF--
+Parent class:
+bool(false)
+
+Methods:
+ok
+
+Class variables:
+affected_rows
+errno
+error
+error_list
+field_count
+id
+insert_id
+num_rows
+param_count
+sqlstate
+
+Object variables:
+affected_rows
+insert_id
+num_rows
+param_count
+field_count
+errno
+error
+error_list
+sqlstate
+id
+
+Magic, magic properties:
+
+Warning: mysqli_stmt_affected_rows(): invalid object or resource mysqli_stmt
+ in %s on line %d
+
+Warning: main(): Property access is not allowed yet in %s on line %d
+
+Warning: main(): Property access is not allowed yet in %s on line %d
+stmt->affected_rows = ''
+stmt->affected_rows = '1'
+stmt->errno = '0'
+stmt->error = ''
+string(14) "stmt->error = "
+array(0) {
+}
+stmt->field_count = '0'
+stmt->id = '%d'
+stmt->insert_id = '0'
+stmt->num_rows = '0'
+stmt->param_count = '0'
+stmt->sqlstate = '00000'
+
+Access to undefined properties:
+stmt->unknown = ''
+stmt->unknown = '13'
+
+Prepare using the constructor:
+
+Warning: mysqli_stmt::__construct() expects parameter 2 to be %binary_string_optional%, object given in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_class_mysqli_warning.phpt b/ext/mysqli/tests/mysqli_class_mysqli_warning.phpt
new file mode 100644
index 0000000..62f01ca
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_class_mysqli_warning.phpt
@@ -0,0 +1,132 @@
+--TEST--
+Interface of the class mysqli_warning - TODO
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+require_once('connect.inc');
+
+if (!$TEST_EXPERIMENTAL)
+ die("skip - experimental (= unsupported) feature");
+?>
+--FILE--
+<?php
+ require('connect.inc');
+
+ $warning = new mysqli_warning();
+ $warning = new mysqli_warning(null);
+ $warning = new mysqli_warning(null, null);
+
+ $mysqli = new mysqli();
+ $warning = new mysqli_warning($mysqli);
+
+ $mysqli = new my_mysqli($host, $user, $passwd, $db, $port, $socket);
+ $stmt = new mysqli_stmt($mysqli);
+ $warning = new mysqli_warning($stmt);
+
+ $stmt = $mysqli->stmt_init();
+ $warning = new mysqli_warning($stmt);
+
+ $obj = new stdClass();
+ $warning = new mysqli_warning($obj);
+
+ include("table.inc");
+ $mysqli = new my_mysqli($host, $user, $passwd, $db, $port, $socket);
+ $res = $mysqli->query('INSERT INTO test(id, label) VALUES (1, "zz")');
+ $warning = mysqli_get_warnings($mysqli);
+
+ printf("Parent class:\n");
+ var_dump(get_parent_class($warning));
+
+ printf("\nMethods:\n");
+ $methods = get_class_methods($warning);
+ $expected_methods = array(
+ 'next' => true,
+ );
+
+ foreach ($methods as $k => $method) {
+ if (isset($expected_methods[$method])) {
+ unset($methods[$k]);
+ unset($expected_methods[$method]);
+ }
+ }
+ if (!empty($methods)) {
+ printf("Dumping list of unexpected methods.\n");
+ var_dump($methods);
+ }
+ if (!empty($expected_methods)) {
+ printf("Dumping list of missing methods.\n");
+ var_dump($expected_methods);
+ }
+ if (empty($methods) && empty($expected_methods))
+ printf("ok\n");
+
+ printf("\nClass variables:\n");
+ $variables = get_class_vars(get_class($mysqli));
+ sort($variables);
+ foreach ($variables as $k => $var)
+ printf("%s\n", $var);
+
+ printf("\nObject variables:\n");
+ $variables = get_object_vars($mysqli);
+ foreach ($variables as $k => $var)
+ printf("%s\n", $var);
+
+ printf("\nMagic, magic properties:\n");
+
+ assert('' === $warning->message);
+ printf("warning->message = '%s'\n", $warning->message);
+
+ assert('' === $warning->sqlstate);
+ printf("warning->sqlstate= '%s'\n", $warning->sqlstate);
+
+ assert(0 === $warning->errno);
+ printf("warning->errno = '%s'\n", $warning->errno);
+
+ printf("\nAccess to undefined properties:\n");
+ printf("warning->unknown = '%s'\n", @$warning->unknown);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Warning: Wrong parameter count for mysqli_warning::mysqli_warning() in %s on line %d
+
+Warning: mysqli_warning::mysqli_warning() expects parameter 1 to be object, null given in %s on line %d
+
+Warning: Wrong parameter count for mysqli_warning::mysqli_warning() in %s on line %d
+
+Warning: mysqli_warning::mysqli_warning(): Couldn't fetch mysqli in %s on line %d
+
+Warning: mysqli_warning::mysqli_warning(): invalid object or resource mysqli_stmt
+ in %s on line %d
+
+Warning: mysqli_warning::mysqli_warning(): invalid object or resource mysqli_stmt
+ in %s on line %d
+
+Warning: mysqli_warning::mysqli_warning(): invalid class argument in /home/nixnutz/php6_mysqlnd/ext/mysqli/tests/mysqli_class_mysqli_warning.php on line 19
+
+Warning: mysqli_warning::mysqli_warning(): No warnings found in %s on line %d
+Parent class:
+bool(false)
+
+Methods:
+ok
+
+Class variables:
+
+Object variables:
+
+Magic, magic properties:
+warning->message = ''
+warning->sqlstate= ''
+warning->errno = ''
+
+Access to undefined properties:
+
+warning->unknown = ''
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_class_mysqli_warning_reflection.phpt b/ext/mysqli/tests/mysqli_class_mysqli_warning_reflection.phpt
new file mode 100644
index 0000000..dc0c14e
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_class_mysqli_warning_reflection.phpt
@@ -0,0 +1,116 @@
+--TEST--
+Interface of the class mysqli_stmt - Reflection
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('connect.inc');
+
+if (($tmp = substr(PHP_VERSION, 0, strpos(PHP_VERSION, '.'))) && ($tmp < 5))
+ die("skip Reflection not available before PHP 5 (found PHP $tmp)");
+
+/*
+Let's not deal with cross-version issues in the EXPECTF/UEXPECTF.
+Most of the things which we test are covered by mysqli_class_*_interface.phpt.
+Those tests go into the details and are aimed to be a development tool, no more.
+*/
+if (!$IS_MYSQLND)
+ die("skip Test has been written for the latest version of mysqlnd only");
+if ($MYSQLND_VERSION < 50004)
+ die("skip Test requires mysqlnd Revision 5.0.4 or newer");
+?>
+--FILE--
+<?php
+ require_once('reflection_tools.inc');
+ $class = new ReflectionClass('mysqli_warning');
+ inspectClass($class);
+ print "done!\n";
+?>
+--EXPECTF--
+Inspecting class 'mysqli_warning'
+isInternal: yes
+isUserDefined: no
+isInstantiable: no
+isInterface: no
+isAbstract: no
+isFinal: yes
+isIteratable: no
+Modifiers: '%d'
+Parent Class: ''
+Extension: 'mysqli'
+
+Inspecting method '__construct'
+isFinal: no
+isAbstract: no
+isPublic: no
+isPrivate: no
+isProtected: yes
+isStatic: no
+isConstructor: yes
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: %d
+Number of Parameters: 0
+Number of Required Parameters: 0
+
+Inspecting method '__construct'
+isFinal: no
+isAbstract: no
+isPublic: no
+isPrivate: no
+isProtected: yes
+isStatic: no
+isConstructor: yes
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: %d
+Number of Parameters: 0
+Number of Required Parameters: 0
+
+Inspecting method 'next'
+isFinal: no
+isAbstract: no
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isConstructor: no
+isDestructor: no
+isInternal: yes
+isUserDefined: no
+returnsReference: no
+Modifiers: %d
+Number of Parameters: 0
+Number of Required Parameters: 0
+
+Inspecting property 'errno'
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isDefault: yes
+Modifiers: 256
+
+Inspecting property 'message'
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isDefault: yes
+Modifiers: 256
+
+Inspecting property 'sqlstate'
+isPublic: yes
+isPrivate: no
+isProtected: no
+isStatic: no
+isDefault: yes
+Modifiers: 256
+Default property 'errno'
+Default property 'message'
+Default property 'sqlstate'
+done!
diff --git a/ext/mysqli/tests/mysqli_close.phpt b/ext/mysqli/tests/mysqli_close.phpt
new file mode 100644
index 0000000..c6ac92d
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_close.phpt
@@ -0,0 +1,40 @@
+--TEST--
+mysqli_close()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_close()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_close($link, $link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[003] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ $tmp = @mysqli_close(NULL);
+ if (NULL !== $tmp)
+ printf("[004] Expecting NULL/NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ $tmp = mysqli_close($link);
+ if (true !== $tmp)
+ printf("[005] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_query($link, "SELECT 1")))
+ printf("[006] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_close_oo.phpt b/ext/mysqli/tests/mysqli_close_oo.phpt
new file mode 100644
index 0000000..be67f77
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_close_oo.phpt
@@ -0,0 +1,36 @@
+--TEST--
+mysqli_close()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!$mysqli = new my_mysqli($host, $user, $passwd, $db, $port, $socket))
+ printf("[001] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ if (!is_null($tmp = @$mysqli->close($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ $tmp = $mysqli->close();
+ if (true !== $tmp)
+ printf("[003] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @$mysqli->close()))
+ printf("[004] Expecting NULL got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @$mysqli->query("SELECT 1")))
+ printf("[005] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_commit.phpt b/ext/mysqli/tests/mysqli_commit.phpt
new file mode 100644
index 0000000..d20ba5d
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_commit.phpt
@@ -0,0 +1,77 @@
+--TEST--
+mysqli_commit()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+require_once('connect.inc');
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ die(sprintf("Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error()));
+
+if (!have_innodb($link))
+ die(sprintf("Needs InnoDB support, [%d] %s", $link->errno, $link->error));
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_commit()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_commit($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_commit($link, $link)))
+ printf("[003] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[004] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ if (true !== ($tmp = mysqli_autocommit($link, false)))
+ printf("[005] Cannot turn off autocommit, expecting true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_query($link, 'DROP TABLE IF EXISTS test'))
+ printf("[006] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, 'CREATE TABLE test(id INT) ENGINE = InnoDB'))
+ printf("[007] Cannot create test table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, 'INSERT INTO test(id) VALUES (1)'))
+ printf("[008] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $tmp = mysqli_commit($link);
+ if ($tmp !== true)
+ printf("[009] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_query($link, 'ROLLBACK'))
+ printf("[010] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$res = mysqli_query($link, 'SELECT COUNT(*) AS num FROM test'))
+ printf("[011] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ $tmp = mysqli_fetch_assoc($res);
+ if (1 != $tmp['num'])
+ printf("[12] Expecting 1 row in table test, found %d rows\n", $tmp['num']);
+ mysqli_free_result($res);
+
+ if (!mysqli_query($link, 'DROP TABLE IF EXISTS test'))
+ printf("[013] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ mysqli_close($link);
+
+ if (NULL !== ($tmp = @mysqli_commit($link)))
+ printf("[014] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_commit_oo.phpt b/ext/mysqli/tests/mysqli_commit_oo.phpt
new file mode 100644
index 0000000..34ec4bf
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_commit_oo.phpt
@@ -0,0 +1,79 @@
+--TEST--
+mysqli_commit()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+require_once('connect.inc');
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ die(sprintf("Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error()));
+
+if (!have_innodb($link))
+ die(sprintf("Needs InnoDB support, [%d] %s", $link->errno, $link->error));
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ $mysqli = new mysqli();
+ if (!is_null($tmp = @$mysqli->commit()))
+ printf("[013] Expecting NULL got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$mysqli = new my_mysqli($host, $user, $passwd, $db, $port, $socket))
+ printf("[001] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ if (!is_null($tmp = @$mysqli->commit($link)))
+ printf("[002] Expecting NULL/NULL, got %s/%s, [%d] %s\n",
+ gettype($tmp), $tmp, $mysqli->errno, $mysqli->error);
+
+ if (true !== ($tmp = $mysqli->commit()))
+ printf("[014] Expecting boolean/true got %s/%s\n", gettype($tmp), $tmp);
+
+ if (true !== ($tmp = $mysqli->autocommit(false)))
+ printf("[003] Cannot turn off autocommit, expecting true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$mysqli->query('DROP TABLE IF EXISTS test'))
+ printf("[004] [%d] %s\n", $mysqli->errno, $mysqli->error);
+
+ if (!$mysqli->query('CREATE TABLE test(id INT) ENGINE = InnoDB'))
+ printf("[005] Cannot create test table, [%d] %s\n", $mysqli->errno, $mysqli->error);
+
+ if (!$mysqli->query('INSERT INTO test(id) VALUES (1)'))
+ printf("[006] [%d] %s\n", $mysqli->errno, $mysqli->error);
+
+ $tmp = $mysqli->commit();
+ if ($tmp !== true)
+ printf("[007] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$mysqli->query('ROLLBACK'))
+ printf("[008] [%d] %s\n", $mysqli->errno, $mysqli->error);
+
+ if (!$res = $mysqli->query('SELECT COUNT(*) AS num FROM test'))
+ printf("[009] [%d] %s\n", $mysqli->errno, $mysqli->error);
+ $tmp = $res->fetch_assoc();
+ if (1 != $tmp['num'])
+ printf("[010] Expecting 1 row in table test, found %d rows\n", $tmp['num']);
+ $res->free();
+
+ if (!$mysqli->query('DROP TABLE IF EXISTS test'))
+ printf("[011] [%d] %s\n", $mysqli->errno, $mysqli->error);
+
+ $mysqli->close();
+
+ if (NULL !== ($tmp = @$mysqli->commit()))
+ printf("[012] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_connect.phpt b/ext/mysqli/tests/mysqli_connect.phpt
new file mode 100644
index 0000000..e14d88f
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_connect.phpt
@@ -0,0 +1,175 @@
+--TEST--
+mysqli_connect()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ /* we need to check, if the server allows anonymous login (empty user) */
+ $tmp = @mysqli_connect('localhost');
+ $anon_allow = (gettype($tmp) == "object");
+
+ $exptype = ($anon_allow) ? "mysqli_object" : "false";
+
+ $obj = new stdClass();
+ if (!is_null($tmp = @mysqli_connect($obj)))
+ printf("[001] Expecting NULL got %s/%s\n", gettype($tmp), $tmp);
+
+ $tmp = @mysqli_connect($link);
+ if (($anon_allow && gettype($tmp) != "object") || (!$anon_allow && $tmp != false)) {
+ printf("[002] Expecting %s, got %s/%s\n", $exptype, gettype($tmp), $tmp);
+ }
+
+ $tmp = @mysqli_connect($link, $link);
+ if (($anon_allow && gettype($tmp) != "object") || (!$anon_allow && $tmp != false)) {
+ printf("[003] Expecting %s, got %s/%s\n", $exptype, gettype($tmp), $tmp);
+ }
+
+ $tmp = @mysqli_connect($link, $link, $link);
+ if (($anon_allow && gettype($tmp) != "object") || (!$anon_allow && $tmp != false)) {
+ printf("[004] Expecting %s, got %s/%s\n", $exptype, gettype($tmp), $tmp);
+ }
+
+ $tmp = @mysqli_connect($link, $link, $link, $link);
+ if (($anon_allow && gettype($tmp) != "object") || (!$anon_allow && $tmp != false)) {
+ printf("[005] Expecting %s, got %s/%s\n", $exptype, gettype($tmp), $tmp);
+ }
+
+ $tmp = @mysqli_connect($link, $link, $link, $link, $link);
+ if (($anon_allow && gettype($tmp) != "object") || (!$anon_allow && $tmp != false)) {
+ printf("[006] Expecting %s, got %s/%s\n", $exptype, gettype($tmp), $tmp);
+ }
+
+ $tmp = @mysqli_connect($link, $link, $link, $link, $link, $link);
+ if (($anon_allow && gettype($tmp) != "object") || (!$anon_allow && $tmp != false)) {
+ printf("[007] Expecting %s, got %s/%s\n", $exptype, gettype($tmp), $tmp);
+ }
+
+ if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[008] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ mysqli_close($link);
+
+ if ($link = mysqli_connect($host, $user . 'unknown_really', $passwd . 'non_empty', $db, $port, $socket))
+ printf("[009] Can connect to the server using host=%s, user=%s, passwd=***non_empty, dbname=%s, port=%s, socket=%s\n",
+ $host, $user . 'unknown_really', $db, $port, $socket);
+
+ if (false !== $link)
+ printf("[010] Expecting boolean/false, got %s/%s\n", gettype($link), $link);
+
+ // Run the following tests without an anoynmous MySQL user and use a password for the test user!
+ ini_set('mysqli.default_socket', $socket);
+ if (!is_object($link = mysqli_connect($host, $user, $passwd, $db, $port))) {
+ printf("[011] Usage of mysqli.default_socket failed\n") ;
+ } else {
+ if (!$res = mysqli_query($link, "SELECT 'mysqli.default_socket' AS 'testing'"))
+ printf("[012] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ var_dump(mysqli_fetch_assoc($res));
+ mysqli_free_result($res);
+ mysqli_close($link);
+ }
+
+ ini_set('mysqli.default_port', $port);
+ if (!is_object($link = mysqli_connect($host, $user, $passwd, $db))) {
+ printf("[013] Usage of mysqli.default_port failed\n") ;
+ } else {
+ if (!$res = mysqli_query($link, "SELECT 'mysqli.default_port' AS 'testing'"))
+ printf("[014] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ var_dump(mysqli_fetch_assoc($res));
+ mysqli_free_result($res);
+ mysqli_close($link);
+ }
+
+ ini_set('mysqli.default_pw', $passwd);
+ if (!is_object($link = mysqli_connect($host, $user))) {
+ printf("[015] Usage of mysqli.default_pw failed\n") ;
+ } else {
+ if (!$res = mysqli_query($link, "SELECT 'mysqli.default_pw' AS 'testing'"))
+ printf("[016] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ var_dump(mysqli_fetch_assoc($res));
+ mysqli_free_result($res);
+ mysqli_close($link);
+ }
+
+ ini_set('mysqli.default_user', $user);
+ if (!is_object($link = mysqli_connect($host))) {
+ printf("[017] Usage of mysqli.default_user failed\n") ;
+ } else {
+ if (!$res = mysqli_query($link, "SELECT 'mysqli.default_user' AS 'testing'"))
+ printf("[018] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ var_dump(mysqli_fetch_array($res, MYSQLI_BOTH));
+ mysqli_free_result($res);
+ mysqli_close($link);
+ }
+
+ ini_set('mysqli.default_host', $host);
+ if (!is_object($link = mysqli_connect())) {
+ printf("[019] Usage of mysqli.default_host failed\n") ;
+ } else {
+ if (!$res = mysqli_query($link, "SELECT 'mysqli.default_host' AS 'testing'"))
+ printf("[020] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ var_dump(mysqli_fetch_array($res, MYSQLI_NUM));
+ mysqli_free_result($res);
+ mysqli_close($link);
+ }
+
+ if ($IS_MYSQLND) {
+ ini_set('mysqli.default_host', 'p:' . $host);
+ if (!is_object($link = mysqli_connect())) {
+ printf("[021] Usage of mysqli.default_host (persistent) failed\n") ;
+ } else {
+ if (!$res = mysqli_query($link, "SELECT 'mysqli.default_host (persistent)' AS 'testing'"))
+ printf("[022] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ $tmp = mysqli_fetch_assoc($res);
+ if ($tmp['testing'] !== 'mysqli.default_host (persistent)') {
+ printf("[023] Result looks strange - check manually, [%d] %s\n",
+ mysqli_errno($link), mysqli_error($link));
+ var_dump($tmp);
+ }
+ mysqli_free_result($res);
+ mysqli_close($link);
+ }
+
+ ini_set('mysqli.default_host', 'p:');
+ if (is_object($link = @mysqli_connect())) {
+ printf("[024] Usage of mysqli.default_host=p: did not fail\n") ;
+ mysqli_close($link);
+ }
+ }
+
+ print "done!";
+?>
+--EXPECTF--
+Warning: mysqli_connect(): (%s/%d): Access denied for user '%s'@'%s' (using password: YES) in %s on line %d
+array(1) {
+ [%u|b%"testing"]=>
+ %unicode|string%(21) "mysqli.default_socket"
+}
+array(1) {
+ [%u|b%"testing"]=>
+ %unicode|string%(19) "mysqli.default_port"
+}
+array(1) {
+ [%u|b%"testing"]=>
+ %unicode|string%(17) "mysqli.default_pw"
+}
+array(2) {
+ [0]=>
+ %unicode|string%(19) "mysqli.default_user"
+ [%u|b%"testing"]=>
+ %unicode|string%(19) "mysqli.default_user"
+}
+array(1) {
+ [0]=>
+ %unicode|string%(19) "mysqli.default_host"
+}
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_connect_errno.phpt b/ext/mysqli/tests/mysqli_connect_errno.phpt
new file mode 100644
index 0000000..a7f90f1
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_connect_errno.phpt
@@ -0,0 +1,40 @@
+--TEST--
+mysqli_connect_errno()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ // too many parameter
+ if (0 !== ($tmp = @mysqli_connect_errno($link)))
+ printf("[001] Expecting integer/0, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[002] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ if (0 !== ($tmp = mysqli_connect_errno()))
+ printf("[003] Expecting integer/0, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_close($link);
+
+ $link = @my_mysqli_connect($host, $user . 'unknown_really', $passwd . 'non_empty', $db, $port, $socket);
+ if (false !== $link)
+ printf("[004] Connect to the server should fail using host=%s, user=%s, passwd=***non_empty, dbname=%s, port=%s, socket=%s, expecting boolean/false, got %s/%s\n",
+ $host, $user . 'unknown_really', $db, $port, $socket, gettype($link), var_export($link, true));
+
+ if (0 === ($tmp = mysqli_connect_errno()))
+ printf("[005] Expecting integer/any non-zero, got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_connect_error.phpt b/ext/mysqli/tests/mysqli_connect_error.phpt
new file mode 100644
index 0000000..79ac3f1
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_connect_error.phpt
@@ -0,0 +1,39 @@
+--TEST--
+mysqli_connect_error()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ // too many parameter
+ if (!is_null($tmp = @mysqli_connect_error($link)))
+ printf("[001] Expecting NULL/NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[002] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ if (NULL !== ($tmp = mysqli_connect_error()))
+ printf("[003] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_close($link);
+
+ if ($link = @my_mysqli_connect($host, $user . 'unknown_really', $passwd . 'non_empty', $db, $port, $socket))
+ printf("[003] Connect to the server should fail using host=%s, user=%s, passwd=***non_empty, dbname=%s, port=%s, socket=%s\n",
+ $host, $user . 'unknown_really', $db, $port, $socket);
+
+ if ('' === ($tmp = mysqli_connect_error()))
+ printf("[004] Expecting string/'', got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_connect_oo.phpt b/ext/mysqli/tests/mysqli_connect_oo.phpt
new file mode 100644
index 0000000..35cc116
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_connect_oo.phpt
@@ -0,0 +1,153 @@
+--TEST--
+new mysqli()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ $obj = new stdClass();
+
+ if ($mysqli = new mysqli($host, $user . 'unknown_really', $passwd . 'non_empty', $db, $port, $socket) && !mysqli_connect_errno())
+ printf("[003] Can connect to the server using host=%s, user=%s, passwd=***non_empty, dbname=%s, port=%s, socket=%s\n",
+ $host, $user . 'unknown_really', $db, $port, $socket);
+
+ if (false !== $mysqli)
+ printf("[004] Expecting boolean/false, got %s/%s\n", gettype($mysqli), $mysqli);
+
+ // Run the following tests without an anoynmous MySQL user and use a password for the test user!
+ ini_set('mysqli.default_socket', $socket);
+ if (!is_object($mysqli = new mysqli($host, $user, $passwd, $db, $port)) || (0 !== mysqli_connect_errno())) {
+ printf("[005] Usage of mysqli.default_socket failed\n") ;
+ } else {
+ $mysqli->close();
+ }
+
+ ini_set('mysqli.default_port', $port);
+ if (!is_object($mysqli = new mysqli($host, $user, $passwd, $db)) || (0 !== mysqli_connect_errno())) {
+ printf("[006] Usage of mysqli.default_port failed\n") ;
+ } else {
+ $mysqli->close();
+ }
+
+ ini_set('mysqli.default_pw', $passwd);
+ if (!is_object($mysqli = new mysqli($host, $user)) || (0 !== mysqli_connect_errno())) {
+ printf("[007] Usage of mysqli.default_pw failed\n") ;
+ } else {
+ $mysqli->close();
+ }
+
+ ini_set('mysqli.default_user', $user);
+ if (!is_object($mysqli = new mysqli($host)) || (0 !== mysqli_connect_errno())) {
+ printf("[008] Usage of mysqli.default_user failed\n") ;
+ } else {
+ $mysqli->close();
+ }
+
+ ini_set('mysqli.default_host', $host);
+ if (!is_object($mysqli = new mysqli()) || (0 !== mysqli_connect_errno())) {
+ printf("[012] Failed to create mysqli object\n");
+ } else {
+ // There shall be NO connection! Using new mysqli(void) shall not use defaults for a connection!
+ // We had long discussions on this and found that the ext/mysqli API as
+ // such is broken. As we can't fix it, we document how it has behaved from
+ // the first day on. And that's: no connection.
+ if (NULL !== ($tmp = @$mysqli->query('SELECT 1'))) {
+ printf("[013] There shall be no connection!\n");
+ $mysqli->close();
+ }
+ }
+
+ if ($IS_MYSQLND) {
+ ini_set('mysqli.default_host', 'p:' . $host);
+ if (!is_object($mysqli = new mysqli())) {
+ // Due to an API flaw this shall not connect
+ printf("[010] Failed to create mysqli object\n");
+ } else {
+ // There shall be NO connection! Using new mysqli(void) shall not use defaults for a connection!
+ // We had long discussions on this and found that the ext/mysqli API as
+ // such is broken. As we can't fix it, we document how it has behaved from
+ // the first day on. And that's: no connection.
+ if (NULL !== ($tmp = @$mysqli->query('SELECT 1'))) {
+ printf("[011] There shall be no connection!\n");
+ $mysqli->close();
+ }
+ }
+ }
+
+ print "... and now Exceptions\n";
+ mysqli_report(MYSQLI_REPORT_OFF);
+ mysqli_report(MYSQLI_REPORT_STRICT);
+
+ try {
+ $mysqli = new mysqli($host, $user . 'unknown_really', $passwd . 'non_empty', $db, $port, $socket);
+ printf("[016] Can connect to the server using host=%s, user=%s, passwd=***non_empty, dbname=%s, port=%s, socket=%s\n",
+ $host, $user . 'unknown_really', $db, $port, $socket);
+ $mysqli->close();
+ } catch (mysqli_sql_exception $e) {
+ printf("%s\n", $e->getMessage());
+ }
+
+ ini_set('mysqli.default_socket', $socket);
+ try {
+ $mysqli = new mysqli($host, $user, $passwd, $db, $port);
+ $mysqli->close();
+ } catch (mysqli_sql_exception $e) {
+ printf("%s\n", $e->getMessage());
+ printf("[017] Usage of mysqli.default_socket failed\n") ;
+ }
+
+ ini_set('mysqli.default_port', $port);
+ try {
+ $mysqli = new mysqli($host, $user, $passwd, $db);
+ $mysqli->close();
+ } catch (mysqli_sql_exception $e) {
+ printf("%s\n", $e->getMessage());
+ printf("[018] Usage of mysqli.default_port failed\n") ;
+ }
+
+ ini_set('mysqli.default_pw', $passwd);
+ try {
+ $mysqli = new mysqli($host, $user);
+ $mysqli->close();
+ } catch (mysqli_sql_exception $e) {
+ printf("%s\n", $e->getMessage());
+ printf("[019] Usage of mysqli.default_pw failed\n");
+ }
+
+ ini_set('mysqli.default_user', $user);
+ try {
+ $mysqli = new mysqli($host);
+ $mysqli->close();
+ } catch (mysqli_sql_exception $e) {
+ printf("%s\n", $e->getMessage());
+ printf("[020] Usage of mysqli.default_user failed\n") ;
+ }
+
+ ini_set('mysqli.default_host', $host);
+ try {
+ /* NOTE that at this point one must use a different syntax! */
+ $mysqli = mysqli_init();
+ $mysqli->real_connect();
+ assert(0 === mysqli_connect_errno());
+ $mysqli->close();
+ assert(0 === mysqli_connect_errno());
+ } catch (mysqli_sql_exception $e) {
+ printf("%s\n", $e->getMessage());
+ printf("[021] Usage of mysqli.default_host failed\n");
+ }
+
+ print "done!";
+?>
+--EXPECTF--
+Warning: mysqli::mysqli(): (%s/%d): Access denied for user '%sunknown%s'@'%s' (using password: %s) in %s on line %d
+... and now Exceptions
+Access denied for user '%s'@'%s' (using password: %s)
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_connect_oo_defaults.phpt b/ext/mysqli/tests/mysqli_connect_oo_defaults.phpt
new file mode 100644
index 0000000..1855a20
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_connect_oo_defaults.phpt
@@ -0,0 +1,180 @@
+--TEST--
+new mysqli()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if ($socket != "")
+ /* mysqli.default_socket requires non-empty string */
+ ini_set('mysqli.default_socket', 'socket');
+
+ ini_set('mysqli.default_port', 9999);
+ ini_set('mysqli.default_pw', 'password');
+ ini_set('mysqli.default_user', 'user');
+ ini_set('mysqli.default_host', 'host');
+
+ mysqli_report(MYSQLI_REPORT_OFF);
+ mysqli_report(MYSQLI_REPORT_STRICT);
+
+ if ($socket != "") {
+ ini_set('mysqli.default_socket', $socket);
+ try {
+ $mysqli = mysqli_init();
+ $mysqli->real_connect($host, $user, $passwd, $db, $port);
+
+ if (!$res = $mysqli->query("SELECT 'mysqli.default_socket' AS testing"))
+ printf("[001] [%d] %s\n", $mysqli->errno, $mysqli->error);
+ $tmp = $res->fetch_assoc();
+ $res->free_result();
+
+ if (!isset($tmp['testing']) || $tmp['testing'] != 'mysqli.default_socket') {
+ printf("[002] mysqli.default_socket not properly set?\n");
+ var_dump($tmp);
+ }
+
+ $mysqli->close();
+
+ } catch (mysqli_sql_exception $e) {
+ printf("%s\n", $e->getMessage());
+ printf("[002] Usage of mysqli.default_socket failed\n");
+ }
+ }
+
+ ini_set('mysqli.default_port', $port);
+ try {
+ $mysqli = mysqli_init();
+ $mysqli->real_connect($host, $user, $passwd, $db);
+
+ if (!$res = $mysqli->query("SELECT 'mysqli.default_port' AS testing"))
+ printf("[003] [%d] %s\n", $mysqli->errno, $mysqli->error);
+ var_dump($res->fetch_assoc());
+ $res->free_result();
+
+ $mysqli->close();
+
+ } catch (mysqli_sql_exception $e) {
+ printf("%s\n", $e->getMessage());
+ printf("[004] Usage of mysqli.default_port failed\n");
+ }
+
+ ini_set('mysqli.default_pw', $passwd);
+ try {
+ $mysqli = mysqli_init();
+ $mysqli->real_connect($host, $user);
+ $mysqli->select_db($db);
+
+ if (!$res = $mysqli->query("SELECT 'mysqli.default_pw' AS testing"))
+ printf("[005] [%d] %s\n", $mysqli->errno, $mysqli->error);
+ var_dump($res->fetch_assoc());
+ $res->free_result();
+
+ $mysqli->close();
+
+ } catch (mysqli_sql_exception $e) {
+ printf("%s\n", $e->getMessage());
+ printf("[006] Usage of mysqli.default_pw failed\n");
+ }
+
+ ini_set('mysqli.default_user', $user);
+ try {
+ $mysqli = mysqli_init();
+ $mysqli->real_connect($host);
+ $mysqli->select_db($db);
+
+ if (!$res = $mysqli->query("SELECT 'mysqli.default_user' AS testing"))
+ printf("[007] [%d] %s\n", $mysqli->errno, $mysqli->error);
+ var_dump($res->fetch_assoc());
+ $res->free_result();
+
+ $mysqli->close();
+
+ } catch (mysqli_sql_exception $e) {
+ printf("%s\n", $e->getMessage());
+ printf("[008] Usage of mysqli.default_user failed\n");
+ }
+
+ ini_set('mysqli.default_host', $host);
+ try {
+ $mysqli = mysqli_init();
+ $mysqli->real_connect();
+ $mysqli->select_db($db);
+
+ if (!$res = $mysqli->query("SELECT 1"))
+ printf("[009] [%d] %s\n", $mysqli->errno, $mysqli->error);
+ $res->free_result();
+
+ if (!$res = $mysqli->query("SELECT SUBSTRING_INDEX(USER(),'@',1) AS username"))
+ printf("[010] [%d] %s\n", $mysqli->errno, $mysqli->error);
+
+ $tmp = $res->fetch_assoc();
+ $res->free_result();
+ if ($tmp['username'] !== $user)
+ printf("[011] Expecting string/%s, got %s/%s\n", $user, gettype($tmp['username']), $tmp['username']);
+
+ $mysqli->close();
+
+ } catch (mysqli_sql_exception $e) {
+ printf("%s\n", $e->getMessage());
+ printf("[012] Usage of mysqli.default_host failed\n");
+ }
+
+ try {
+ $link = mysqli_connect($host, $user, $passwd, null, ini_get('mysqli.default_port'));
+ mysqli_select_db($link, $db);
+ if (!$res = mysqli_query($link, "SELECT 'have been set' AS all_defaults"))
+ printf("[013] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ var_dump(mysqli_fetch_assoc($res));
+ mysqli_free_result($res);
+ mysqli_close($link);
+ } catch (mysqli_sql_exception $e) {
+ printf("%s\n", $e->getMessage());
+ printf("[014] Usage of mysqli_connect() has failed\n");
+ }
+
+ try {
+ $link = mysqli_connect($host, $user, $passwd, null);
+ mysqli_select_db($link, $db);
+ if (!$res = mysqli_query($link, "SELECT 'have been set' AS all_defaults"))
+ printf("[015] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ var_dump(mysqli_fetch_assoc($res));
+ mysqli_free_result($res);
+ mysqli_close($link);
+ } catch (mysqli_sql_exception $e) {
+ printf("%s\n", $e->getMessage());
+ printf("[016] Usage of mysqli_connect() has failed\n");
+ }
+
+
+ print "done!";
+?>
+--EXPECTF--
+array(1) {
+ [%u|b%"testing"]=>
+ %unicode|string%(19) "mysqli.default_port"
+}
+array(1) {
+ [%u|b%"testing"]=>
+ %unicode|string%(17) "mysqli.default_pw"
+}
+array(1) {
+ [%u|b%"testing"]=>
+ %unicode|string%(19) "mysqli.default_user"
+}
+array(1) {
+ [%u|b%"all_defaults"]=>
+ %unicode|string%(13) "have been set"
+}
+array(1) {
+ [%u|b%"all_defaults"]=>
+ %unicode|string%(13) "have been set"
+}
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_connect_oo_warnings.phpt b/ext/mysqli/tests/mysqli_connect_oo_warnings.phpt
new file mode 100644
index 0000000..5ede445
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_connect_oo_warnings.phpt
@@ -0,0 +1,57 @@
+--TEST--
+new mysqli()
+--SKIPIF--
+<?php
+ require_once('skipif.inc');
+ require_once('skipifemb.inc');
+ require_once('skipifconnectfailure.inc');
+ if (!get_current_user())
+ die('skip: get_current_user() not supported');
+ if (stristr(mysqli_get_client_info(), 'mysqlnd'))
+ die("skip: test for libmysql (different error output when using php streams");
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $myhost = 'invalidhost';
+ $link = NULL;
+
+ print "1) bail\n";
+ if (!is_object($mysqli = new mysqli($myhost)) || ('mysqli' !== get_class($mysqli)))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($mysqli), (is_object($mysqli)) ? var_export($mysqli, true) : $mysqli);
+
+ print "2) be quiet\n";
+ if (!is_object($mysqli = @new mysqli($myhost)) || ('mysqli' !== get_class($mysqli)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($mysqli), (is_object($mysqli)) ? var_export($mysqli, true) : $mysqli);
+ var_dump(mysqli_connect_error());
+ var_dump(mysqli_connect_errno());
+
+ print "3) bail\n";
+ if (false !== ($link = mysqli_connect($myhost))) {
+ printf("[003] Expecting boolean/false, got %s/%s\n", gettype($link), $link);
+ }
+
+ print "4) be quiet\n";
+ if (false !== ($link = @mysqli_connect($myhost))) {
+ printf("[004] Expecting boolean/false, got %s/%s\n", gettype($link), $link);
+ }
+ var_dump(mysqli_connect_error());
+ var_dump(mysqli_connect_errno());
+
+ print "done!";
+?>
+--EXPECTF--
+1) bail
+
+Warning: mysqli::mysqli(): (HY000/200%d): %s
+2) be quiet
+%s(%d) "%s"
+int(200%d)
+3) bail
+
+Warning: mysqli_connect(): (HY000/200%d): %s
+4) be quiet
+%s(%d) "%s"
+int(200%d)
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_connect_twice.phpt b/ext/mysqli/tests/mysqli_connect_twice.phpt
new file mode 100644
index 0000000..a9d5b7e
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_connect_twice.phpt
@@ -0,0 +1,84 @@
+--TEST--
+Calling connect() on an open connection to create a new connection
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[001] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ if (!$thread_id = mysqli_thread_id($link))
+ printf("[002] Cannot determine thread id, test will fail, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (true !== ($tmp = my_mysqli_real_connect($link, $host, $user, $passwd, $db, $port, $socket)))
+ printf("[003] Expecting boolean/true got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_int($new_thread_id = mysqli_thread_id($link)) || ($new_thread_id < 0))
+ printf("[004] Expecting int/any got %s/%s\n", gettype($tmp), $tmp);
+
+ if ($thread_id == $new_thread_id)
+ printf("[005] Expecting new connection and new thread id. Old thread id %d, new thread id %d\n", $thread_id, $new_thread_id);
+
+ if (!($res = mysqli_query($link, "SELECT 'ok' AS it_works")) ||
+ !($row = mysqli_fetch_assoc($res)))
+ printf("[006] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ var_dump($row);
+ mysqli_free_result($res);
+
+ mysqli_close($link);
+
+ if (!$link = new my_mysqli($host, $user, $passwd, $db, $port, $socket))
+ printf("[007] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ if (!$thread_id = $link->thread_id)
+ printf("[008] Cannot determine thread id, test will fail, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (true !== ($tmp = $link->real_connect($host, $user, $passwd, $db, $port, $socket)))
+ printf("[009] Expecting boolean/true got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_int($new_thread_id = $link->thread_id) || ($new_thread_id < 0))
+ printf("[010] Expecting int/any got %s/%s\n", gettype($tmp), $tmp);
+
+ if ($thread_id == $new_thread_id)
+ printf("[011] Expecting new connection and new thread id. Old thread id %d, new thread id %d\n", $thread_id, $new_thread_id);
+
+ if (!($res = $link->query("SELECT 'works also with oo' AS syntax")) ||
+ !($row = $res->fetch_assoc()))
+ printf("[012] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ var_dump($row);
+ mysqli_free_result($res);
+
+ mysqli_close($link);
+
+ if (NULL !== ($tmp = $link->connect($host, $user, $passwd, $db, $port, $socket)))
+ printf("[013] Expecting NULL got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[014] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ if (NULL !== ($tmp = $link->connect($host, $user, $passwd, $db, $port, $socket)))
+ printf("[015] Expecting NULL got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--EXPECTF--
+array(1) {
+ [%u|b%"it_works"]=>
+ %unicode|string%(2) "ok"
+}
+array(1) {
+ [%u|b%"syntax"]=>
+ %unicode|string%(18) "works also with oo"
+}
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_constants.phpt b/ext/mysqli/tests/mysqli_constants.phpt
new file mode 100644
index 0000000..8bdc849
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_constants.phpt
@@ -0,0 +1,212 @@
+--TEST--
+Constants exported by ext/mysqli
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require("connect.inc");
+ require("table.inc");
+
+ $php_version = (int)str_replace('.', '', PHP_VERSION);
+ $constants = get_defined_constants(true);
+ sort($constants);
+
+ $expected_constants = array(
+ 'MYSQLI_READ_DEFAULT_GROUP' => true,
+ 'MYSQLI_READ_DEFAULT_FILE' => true,
+ 'MYSQLI_OPT_CONNECT_TIMEOUT' => true,
+ 'MYSQLI_OPT_LOCAL_INFILE' => true,
+ 'MYSQLI_INIT_COMMAND' => true,
+ 'MYSQLI_CLIENT_SSL' => true,
+ "MYSQLI_CLIENT_COMPRESS" => true,
+ "MYSQLI_CLIENT_INTERACTIVE" => true,
+ "MYSQLI_CLIENT_IGNORE_SPACE" => true,
+ "MYSQLI_CLIENT_NO_SCHEMA" => true,
+ "MYSQLI_CLIENT_FOUND_ROWS" => true,
+ "MYSQLI_STORE_RESULT" => true,
+ "MYSQLI_USE_RESULT" => true,
+ "MYSQLI_ASSOC" => true,
+ "MYSQLI_NUM" => true,
+ "MYSQLI_BOTH" => true,
+ "MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH" => true,
+ "MYSQLI_NOT_NULL_FLAG" => true,
+ "MYSQLI_PRI_KEY_FLAG" => true,
+ "MYSQLI_UNIQUE_KEY_FLAG" => true,
+ "MYSQLI_MULTIPLE_KEY_FLAG" => true,
+ "MYSQLI_BLOB_FLAG" => true,
+ "MYSQLI_UNSIGNED_FLAG" => true,
+ "MYSQLI_ZEROFILL_FLAG" => true,
+ "MYSQLI_AUTO_INCREMENT_FLAG" => true,
+ "MYSQLI_TIMESTAMP_FLAG" => true,
+ "MYSQLI_SET_FLAG" => true,
+ "MYSQLI_NUM_FLAG" => true,
+ "MYSQLI_ENUM_FLAG" => true,
+ "MYSQLI_BINARY_FLAG" => true,
+ "MYSQLI_PART_KEY_FLAG" => true,
+ "MYSQLI_GROUP_FLAG" => true,
+ "MYSQLI_SERVER_QUERY_NO_GOOD_INDEX_USED"=> true,
+ "MYSQLI_SERVER_QUERY_NO_INDEX_USED" => true,
+
+ "MYSQLI_TYPE_DECIMAL" => true,
+ "MYSQLI_TYPE_TINY" => true,
+ "MYSQLI_TYPE_SHORT" => true,
+ "MYSQLI_TYPE_LONG" => true,
+ "MYSQLI_TYPE_FLOAT" => true,
+ "MYSQLI_TYPE_DOUBLE" => true,
+ "MYSQLI_TYPE_NULL" => true,
+ "MYSQLI_TYPE_TIMESTAMP" => true,
+ "MYSQLI_TYPE_LONGLONG" => true,
+ "MYSQLI_TYPE_INT24" => true,
+ "MYSQLI_TYPE_DATE" => true,
+ "MYSQLI_TYPE_TIME" => true,
+ "MYSQLI_TYPE_DATETIME" => true,
+ "MYSQLI_TYPE_YEAR" => true,
+ "MYSQLI_TYPE_NEWDATE" => true,
+ "MYSQLI_TYPE_ENUM" => true,
+ "MYSQLI_TYPE_SET" => true,
+ "MYSQLI_TYPE_TINY_BLOB" => true,
+ "MYSQLI_TYPE_MEDIUM_BLOB" => true,
+ "MYSQLI_TYPE_LONG_BLOB" => true,
+ "MYSQLI_TYPE_BLOB" => true,
+ "MYSQLI_TYPE_VAR_STRING" => true,
+ "MYSQLI_TYPE_STRING" => true,
+ "MYSQLI_TYPE_CHAR" => true,
+ "MYSQLI_TYPE_INTERVAL" => true,
+ "MYSQLI_TYPE_GEOMETRY" => true,
+ "MYSQLI_NO_DATA" => true,
+ "MYSQLI_REPORT_INDEX" => true,
+ "MYSQLI_REPORT_STRICT" => true,
+ "MYSQLI_REPORT_ALL" => true,
+ "MYSQLI_REPORT_ERROR" => true,
+ "MYSQLI_REPORT_OFF" => true,
+ "MYSQLI_SET_CHARSET_NAME" => true,
+ "MYSQLI_SET_CHARSET_DIR" => true,
+ "MYSQLI_REFRESH_GRANT" => true,
+ "MYSQLI_REFRESH_LOG" => true,
+ "MYSQLI_REFRESH_TABLES" => true,
+ "MYSQLI_REFRESH_HOSTS" => true,
+ "MYSQLI_REFRESH_STATUS" => true,
+ "MYSQLI_REFRESH_THREADS" => true,
+ "MYSQLI_REFRESH_SLAVE" => true,
+ "MYSQLI_REFRESH_MASTER" => true,
+ "MYSQLI_DEBUG_TRACE_ENABLED" => true,
+ );
+
+ /* depends on the build - experimental */
+ if ($IS_MYSQLND && defined('MYSQLI_OPT_INT_AND_FLOAT_NATIVE')) {
+ $expected_constants['MYSQLI_OPT_INT_AND_FLOAT_NATIVE'] = true;
+ }
+
+ if ($IS_MYSQLND || defined('MYSQLI_REFRESH_BACKUP_LOG')) {
+ $expected_constants['MYSQLI_REFRESH_BACKUP_LOG'] = true;
+ }
+
+ if ($IS_MYSQLND) {
+ $version = 50007 + 1;
+ $expected_constants['MYSQLI_OPT_NET_CMD_BUFFER_SIZE'] = true;
+ $expected_constants['MYSQLI_OPT_NET_READ_BUFFER_SIZE'] = true;
+ $expected_constants['MYSQLI_ASYNC'] = true;
+
+ $expected_constants['MYSQLI_SERVER_PS_OUT_PARAMS'] = true;
+ } else {
+ $version = mysqli_get_client_version();
+ }
+
+ if (($version > 51122 && $version < 60000) || ($version > 60003) || $IS_MYSQLND) {
+ $expected_constants['MYSQLI_ON_UPDATE_NOW_FLAG'] = true;
+ }
+
+ /* First introduced in MySQL 6.0, backported to MySQL 5.5 */
+ if ($version >= 50500 || $IS_MYSQLND) {
+ $expected_constants['MYSQLI_SERVER_QUERY_WAS_SLOW'] = true;
+ }
+
+ if ($version > 50002) {
+ $expected_constants = array_merge($expected_constants, array(
+ "MYSQLI_TYPE_NEWDECIMAL" => true,
+ "MYSQLI_TYPE_BIT" => true,
+ ));
+ }
+
+ if ($version > 50002 || $IS_MYSQLND) {
+ $expected_constants['MYSQLI_NO_DEFAULT_VALUE_FLAG'] = true;
+ }
+
+ if ($version > 50003) {
+ $expected_constants = array_merge($expected_constants, array(
+ "MYSQLI_STMT_ATTR_CURSOR_TYPE" => true,
+ "MYSQLI_CURSOR_TYPE_NO_CURSOR" => true,
+ "MYSQLI_CURSOR_TYPE_READ_ONLY" => true,
+ "MYSQLI_CURSOR_TYPE_FOR_UPDATE" => true,
+ "MYSQLI_CURSOR_TYPE_SCROLLABLE" => true,
+ ));
+ }
+
+ if ($version > 50007) {
+ $expected_constants = array_merge($expected_constants, array(
+ "MYSQLI_STMT_ATTR_PREFETCH_ROWS" => true,
+ ));
+ }
+
+ if ($version > 50110 || $IS_MYSQLND) {
+ $expected_constants['MYSQLI_OPT_SSL_VERIFY_SERVER_CERT'] = true;
+ }
+
+ /* pretty dump test, but that is the best way to mimic mysql.c */
+ if (defined('MYSQLI_DATA_TRUNCATED'))
+ $expected_constants["MYSQLI_DATA_TRUNCATED"] = true;
+
+ if (defined('MYSQLI_SERVER_PS_OUT_PARAMS'))
+ $expected_constants["MYSQLI_SERVER_PS_OUT_PARAMS"] = true;
+
+ if (!$IS_MYSQLND) {
+ /* libmysql only */
+
+ /* are they available in all versions of ext/mysqli ?
+ ... no we must have removed them at some point - for BC, weakening the test
+ */
+ if (defined("MYSQLI_RPL_MASTER")) {
+ $expected_constants["MYSQLI_RPL_MASTER"] = true;
+ $expected_constants["MYSQLI_RPL_SLAVE"] = true;
+ $expected_constants["MYSQLI_RPL_ADMIN"] = true;
+ }
+ }
+
+ if (($IS_MYSQLND && version_compare(PHP_VERSION, ' 5.4.12-dev', '>=')) || (!$IS_MYSQLND && ($version > 50610))) {
+ /* could be that MySQL/libmysql 5.6.9 had the flag already but it was no stable release */
+ $expected_constants["MYSQLI_OPT_CAN_HANDLE_EXPIRED_PASSWORDS"] = true;
+ }
+
+ $unexpected_constants = array();
+
+ foreach ($constants as $group => $consts) {
+ foreach ($consts as $name => $value) {
+ if (stristr($name, 'mysqli')) {
+ $name = strtoupper($name);
+ if (isset($expected_constants[$name])) {
+ unset($expected_constants[$name]);
+ } else {
+ $unexpected_constants[$name] = $name;
+ }
+ }
+ }
+ }
+
+ if (!empty($unexpected_constants)) {
+ printf("Dumping list of unexpected constants\n");
+ var_dump($unexpected_constants);
+ }
+
+ if (!empty($expected_constants)) {
+ printf("Dumping list of missing constants\n");
+ var_dump($expected_constants);
+ }
+
+ print "done!";
+?>
+--EXPECTF--
+done!
diff --git a/ext/mysqli/tests/mysqli_constants_categories.phpt b/ext/mysqli/tests/mysqli_constants_categories.phpt
new file mode 100644
index 0000000..e51325a
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_constants_categories.phpt
@@ -0,0 +1,24 @@
+--TEST--
+Constants exported by ext/mysqli - checking category - PHP bug not mysqli bug (check from time to time)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+?>
+--FILE--
+<?php
+ $constants = get_defined_constants(true);
+
+ foreach ($constants as $group => $consts) {
+ foreach ($consts as $name => $value) {
+ if (stristr($name, 'mysqli')) {
+ if ('mysqli' != $group)
+ printf("found constant '%s' in group '%s'. expecting group 'mysqli'\n", $name, $group);
+ }
+ }
+ }
+
+ print "done!";
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_data_seek.phpt b/ext/mysqli/tests/mysqli_data_seek.phpt
new file mode 100644
index 0000000..9e2d650
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_data_seek.phpt
@@ -0,0 +1,74 @@
+--TEST--
+mysqli_data_seek()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (NULL !== ($tmp = @mysqli_data_seek()))
+ printf("[001] Expecting NULL/NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (NULL !== ($tmp = @mysqli_data_seek($link)))
+ printf("[002] Expecting NULL/NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (NULL !== ($tmp = @mysqli_data_seek($link, $link)))
+ printf("[003] Expecting NULL/NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+ if (!$res = mysqli_query($link, 'SELECT * FROM test ORDER BY id LIMIT 4', MYSQLI_STORE_RESULT))
+ printf("[004] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (true !== ($tmp = mysqli_data_seek($res, 3)))
+ printf("[005] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ $row = mysqli_fetch_assoc($res);
+ if (4 != $row['id'])
+ printf("[006] Expecting record 4/d, got record %s/%s\n", $row['id'], $row['label']);
+
+ if (true !== ($tmp = mysqli_data_seek($res, 0)))
+ printf("[007] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ $row = mysqli_fetch_assoc($res);
+ if (1 != $row['id'])
+ printf("[008] Expecting record 1/a, got record %s/%s\n", $row['id'], $row['label']);
+
+ if (false !== ($tmp = mysqli_data_seek($res, 4)))
+ printf("[009] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (false !== ($tmp = mysqli_data_seek($res, -1)))
+ printf("[010] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_free_result($res);
+
+ if (!$res = mysqli_query($link, 'SELECT * FROM test ORDER BY id', MYSQLI_USE_RESULT))
+ printf("[011] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (false !== ($tmp = mysqli_data_seek($res, 3)))
+ printf("[012] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_free_result($res);
+
+ if (NULL !== ($tmp = mysqli_data_seek($res, 1)))
+ printf("[013] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_close($link);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Warning: mysqli_data_seek(): Function cannot be used with MYSQL_USE_RESULT in %s on line %d
+
+Warning: mysqli_data_seek(): Couldn't fetch mysqli_result in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_data_seek_oo.phpt b/ext/mysqli/tests/mysqli_data_seek_oo.phpt
new file mode 100644
index 0000000..0858218
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_data_seek_oo.phpt
@@ -0,0 +1,83 @@
+--TEST--
+mysqli_result->data_seek()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ require('table.inc');
+
+ if (!$mysqli = new mysqli($host, $user, $passwd, $db, $port, $socket))
+ printf("[001] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ $res = new mysqli_result($mysqli);
+ if (NULL !== ($tmp = @$res->data_seek(0)))
+ printf("[002] Expecting NULL/NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$res = $mysqli->query('SELECT * FROM test ORDER BY id LIMIT 4', MYSQLI_STORE_RESULT))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (NULL !== ($tmp = @$res->data_seek()))
+ printf("[004] Expecting NULL/NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (NULL !== ($tmp = @$res->data_seek($link)))
+ printf("[005] Expecting NULL/NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (NULL !== ($tmp = @$res->data_seek($link, $link)))
+ printf("[006] Expecting NULL/NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (true !== ($tmp = $res->data_seek(3)))
+ printf("[007] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ $row = $res->fetch_assoc();
+ if (4 != $row['id'])
+ printf("[008] Expecting record 4/d, got record %s/%s\n", $row['id'], $row['label']);
+
+ if (true !== ($tmp = $res->data_seek(0)))
+ printf("[009] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ $row = $res->fetch_assoc();
+ if (1 != $row['id'])
+ printf("[010] Expecting record 1/a, got record %s/%s\n", $row['id'], $row['label']);
+
+ if (false !== ($tmp = $res->data_seek(4)))
+ printf("[011] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (false !== ($tmp = $res->data_seek(-1)))
+ printf("[012] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ $res->free_result();
+
+ if (!$res = $mysqli->query('SELECT * FROM test ORDER BY id', MYSQLI_USE_RESULT))
+ printf("[013] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (false !== ($tmp = $res->data_seek(3)))
+ printf("[014] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ $res->free_result();
+
+ if (NULL !== ($tmp = $res->data_seek(1)))
+ printf("[015] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ $mysqli->close();
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Warning: mysqli_result::data_seek(): Function cannot be used with MYSQL_USE_RESULT in %s on line %d
+
+Warning: mysqli_result::data_seek(): Couldn't fetch mysqli_result in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_debug.phpt b/ext/mysqli/tests/mysqli_debug.phpt
new file mode 100644
index 0000000..2b754ea
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_debug.phpt
@@ -0,0 +1,69 @@
+--TEST--
+mysqli_debug()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+if (!function_exists('mysqli_debug'))
+ die("skip: mysqli_debug() not available");
+
+if (!defined('MYSQLI_DEBUG_TRACE_ENABLED'))
+ die("skip: can't say for sure if mysqli_debug works");
+
+if (defined('MYSQLI_DEBUG_TRACE_ENABLED') && !MYSQLI_DEBUG_TRACE_ENABLED)
+ die("skip: debug functionality not enabled");
+?>
+--FILE--
+<?php
+ require_once('connect.inc');;
+
+ if (NULL !== ($tmp = @mysqli_debug()))
+ printf("[001] Expecting NULL/NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ // NOTE: documentation is not clear on this: function always return NULL or TRUE
+ if (true !== ($tmp = mysqli_debug(sprintf('d:t:O,%s/mysqli_debug_phpt.trace', sys_get_temp_dir()))))
+ printf("[002] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if ($IS_MYSQLND) {
+ // let's make this mysqlnd only - for libmysql we need debug installation
+
+ // table.inc will create a database connection and run some SQL queries, therefore
+ // the debug file should have entries
+ require_once('table.inc');
+
+ clearstatcache();
+ $trace_file = sprintf('%s/mysqli_debug_phpt.trace', sys_get_temp_dir());
+ if (!file_exists($trace_file))
+ printf("[003] Trace file '%s' has not been created\n", $trace_file);
+ if (filesize($trace_file) < 50)
+ printf("[004] Trace file '%s' is very small. filesize() reports only %d bytes. Please check.\n",
+ $trace_file,
+ filesize($trace_file));
+
+ // will mysqli_debug() mind if the trace file gets removed?
+ unlink($trace_file);
+ clearstatcache();
+
+ if (!$res = mysqli_query($link, 'SELECT * FROM test'))
+ printf("[005] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ else
+ mysqli_free_result($res);
+
+ mysqli_close($link);
+
+ clearstatcache();
+ if (!file_exists($trace_file))
+ printf("[006] Trace file '%s' does not exist\n", $trace_file);
+ unlink($trace_file);
+ }
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+done%s
diff --git a/ext/mysqli/tests/mysqli_debug_append.phpt b/ext/mysqli/tests/mysqli_debug_append.phpt
new file mode 100644
index 0000000..f916995
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_debug_append.phpt
@@ -0,0 +1,93 @@
+--TEST--
+mysqli_debug() - append to trace file
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+if (!function_exists('mysqli_debug'))
+ die("skip: mysqli_debug() not available");
+
+if (!defined('MYSQLI_DEBUG_TRACE_ENABLED'))
+ die("skip: can't say for sure if mysqli_debug works");
+
+if (defined('MYSQLI_DEBUG_TRACE_ENABLED') && !MYSQLI_DEBUG_TRACE_ENABLED)
+ die("skip: debug functionality not enabled");
+
+if (!$IS_MYSQLND)
+ die("SKIP Libmysql feature not sufficiently spec'd in MySQL C API documentation");
+?>
+--FILE--
+<?php
+ require_once('connect.inc');;
+
+ if (true !== ($tmp = mysqli_debug(sprintf('d:t:O,%s/mysqli_debug_phpt.trace', sys_get_temp_dir()))))
+ printf("[001] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ // table.inc will create a database connection and run some SQL queries, therefore
+ // the debug file should have entries
+ require_once('table.inc');
+
+ clearstatcache();
+ $trace_file = sprintf('%s/mysqli_debug_phpt.trace', sys_get_temp_dir());
+ if (!file_exists($trace_file))
+ printf("[002] Trace file '%s' has not been created\n", $trace_file);
+ if (filesize($trace_file) < 50)
+ printf("[003] Trace file '%s' is very small. filesize() reports only %d bytes. Please check.\n",
+ $trace_file,
+ filesize($trace_file));
+
+ // will mysqli_debug() mind if the trace file gets removed?
+ unlink($trace_file);
+ clearstatcache();
+
+ if (!$fp = fopen($trace_file, 'w')) {
+ printf("[004] Cannot create trace file to test append mode\n");
+ } else {
+
+ if (!fwrite($fp, (binary) 'mysqli_debug.phpt test line'))
+ printf("[005] Cannot write to trace file.\n");
+ fclose($fp);
+
+ if (true !== ($tmp = mysqli_debug(sprintf('d:a,%s', $trace_file))))
+ printf("[006] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$res = mysqli_query($link, 'SELECT * FROM test'))
+ printf("[007] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ else
+ mysqli_free_result($res);
+
+ $trace = file_get_contents($trace_file);
+ if (!strstr($trace, 'mysqli_debug.phpt test line'))
+ printf("[008] Cannot find original file content any more. Seems that the trace file got overwritten and not appended. Please check.");
+
+ if (true !== ($tmp = mysqli_debug(sprintf('d:A,%s', $trace_file))))
+ printf("[009] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$res = mysqli_query($link, 'SELECT * FROM test'))
+ printf("[010] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ else
+ mysqli_free_result($res);
+
+ if (!strstr(file_get_contents($trace_file), $trace))
+ printf("[011] Cannot find original file content any more. Seems that the trace file got overwritten and not appended. Please check.");
+ }
+
+ // what will happen if we create new trace entries...?
+ unlink($trace_file);
+ clearstatcache();
+ if (file_exists($trace_file))
+ printf("[012] Could not remove trace file '%s'.\n", $trace_file);
+
+ mysqli_close($link);
+ print "done";
+ if ($IS_MYSQLND)
+ print "libmysql/DBUG package prints some debug info here."
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+done%s
diff --git a/ext/mysqli/tests/mysqli_debug_control_string.phpt b/ext/mysqli/tests/mysqli_debug_control_string.phpt
new file mode 100644
index 0000000..42a802d
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_debug_control_string.phpt
@@ -0,0 +1,77 @@
+--TEST--
+mysqli_debug() - invalid debug control strings
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+if (!function_exists('mysqli_debug'))
+ die("skip: mysqli_debug() not available");
+
+if (!defined('MYSQLI_DEBUG_TRACE_ENABLED'))
+ die("skip: can't say for sure if mysqli_debug works");
+
+if (defined('MYSQLI_DEBUG_TRACE_ENABLED') && !MYSQLI_DEBUG_TRACE_ENABLED)
+ die("skip: debug functionality not enabled");
+
+if (!$IS_MYSQLND)
+ die("SKIP Libmysql feature not sufficiently spec'd in MySQL C API documentation");
+?>
+--FILE--
+<?php
+ require_once('connect.inc');
+ require_once('table.inc');
+
+ function try_control_string($link, $control_string, $trace_file, $offset) {
+
+ if (true !== ($tmp = mysqli_debug($control_string))) {
+ printf("[%03d][control string '%s'] Expecting boolean/true, got %s/%s.\n",
+ $offset + 1,
+ $control_string,
+ gettype($tmp),
+ $tmp);
+ return false;
+ }
+
+ if (!$res = mysqli_query($link, 'SELECT * FROM test')) {
+ printf("[%03d][control string '%s'] [%d] %s.\n",
+ $offset + 2,
+ $control_string,
+ mysqli_errno($link),
+ mysqli_error($link));
+ return false;
+ }
+
+ clearstatcache();
+ if (!file_exists($trace_file)) {
+ printf("[%03d][control string '%s'] Trace file has not been written.\n",
+ $offset + 3,
+ $control_string,
+ gettype($tmp),
+ $tmp);
+ return false;
+ }
+
+ unlink($trace_file);
+ }
+
+ $trace_file = sprintf('%s%s%s', sys_get_temp_dir(), DIRECTORY_SEPARATOR, 'mysqli_debug_phpt.trace');
+ try_control_string($link, 't:,,:o,' . $trace_file, $trace_file, 10);
+ try_control_string($link, ':' . chr(0) . 'A,' . $trace_file, $trace_file, 20);
+ try_control_string($link, 't:o,' . $trace_file . ':abc', $trace_file, 30);
+ try_control_string($link, 't:o,' . $trace_file . ':ABC,123:b', $trace_file, 40);
+ try_control_string($link, 't:ABC,123:b;:o,' . $trace_file, $trace_file, 50);
+ try_control_string($link, 't:A;BC,123:b;:o,' . $trace_file, $trace_file, 60);
+ try_control_string($link, 't:p:o,' . $trace_file, $trace_file, 70);
+ try_control_string($link, 't:p,1,,2:o,' . $trace_file, $trace_file, 80);
+ try_control_string($link, 't:z,1,,2:o,' . $trace_file, $trace_file, 90);#
+
+ mysqli_close($link);
+ print "done";
+ if ($IS_MYSQLND)
+ print "libmysql/DBUG package prints some debug info here."
+?>
+--EXPECTF--
+[023][control string '%s'] Trace file has not been written.
+done%s
diff --git a/ext/mysqli/tests/mysqli_debug_ini.phpt b/ext/mysqli/tests/mysqli_debug_ini.phpt
new file mode 100644
index 0000000..bcf0067
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_debug_ini.phpt
@@ -0,0 +1,53 @@
+--TEST--
+mysqli_debug() - enabling trace with ini setting
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+if (!function_exists('mysqli_debug'))
+ die("skip mysqli_debug() not available");
+
+if (!defined('MYSQLI_DEBUG_TRACE_ENABLED'))
+ die("skip: can't say for sure if mysqli_debug works");
+
+if (defined('MYSQLI_DEBUG_TRACE_ENABLED') && !MYSQLI_DEBUG_TRACE_ENABLED)
+ die("skip: debug functionality not enabled");
+
+require_once('connect.inc');
+if (!$IS_MYSQLND || ($MYSQLND_VERSION < 50004))
+ die("skip needs mysqlnd version/revision 5.0.4");
+
+if (!$fp = @fopen('/tmp/mysqli_debug_phpt.trace', 'w'))
+ die("skip PHP cannot create a file in /tmp/mysqli_debug_phpt");
+else
+ fclose($fp);
+@unlink("/tmp/mysqli_debug_phpt.trace");
+?>
+--INI--
+mysqlnd.debug="t:O,/tmp/mysqli_debug_phpt.trace"
+--FILE--
+<?php
+ require_once('connect.inc');
+ require_once('table.inc');
+
+ var_dump(ini_get('mysqlnd.debug'));
+
+ $trace_file = '/tmp/mysqli_debug_phpt.trace';
+ clearstatcache();
+ if (!file_exists($trace_file))
+ printf("[003] Trace file '%s' has not been created\n", $trace_file);
+ if (filesize($trace_file) < 50)
+ printf("[004] Trace file '%s' is very small. filesize() reports only %d bytes. Please check.\n",
+ $trace_file,
+ filesize($trace_file));
+
+ mysqli_close($link);
+ unlink($trace_file);
+
+ print "done!";
+?>
+--EXPECTF--
+string(32) "t:O,/tmp/mysqli_debug_phpt.trace"
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_debug_mysqlnd_control_string.phpt b/ext/mysqli/tests/mysqli_debug_mysqlnd_control_string.phpt
new file mode 100644
index 0000000..1de2eeb
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_debug_mysqlnd_control_string.phpt
@@ -0,0 +1,230 @@
+--TEST--
+mysqli_debug() - all control string options supported by both mysqlnd and libmysql except oOaA
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+if (!function_exists('mysqli_debug'))
+ die("skip: mysqli_debug() not available");
+
+if (!defined('MYSQLI_DEBUG_TRACE_ENABLED'))
+ die("skip: can't say for sure if mysqli_debug works");
+
+if (defined('MYSQLI_DEBUG_TRACE_ENABLED') && !MYSQLI_DEBUG_TRACE_ENABLED)
+ die("skip: debug functionality not enabled");
+
+if (!$IS_MYSQLND)
+ die("SKIP Libmysql feature not sufficiently spec'd in MySQL C API documentation");
+?>
+--FILE--
+<?php
+ require_once('connect.inc');;
+ require_once('table.inc');
+
+ function try_control_string($link, $control_string, $trace_file, $offset) {
+
+ @unlink($trace_file);
+ if (true !== ($tmp = @mysqli_debug($control_string))) {
+ printf("[%03d][control string '%s'] Expecting boolean/true, got %s/%s.\n",
+ $offset + 1,
+ $control_string,
+ gettype($tmp),
+ $tmp);
+ return false;
+ }
+
+ if (!$res = mysqli_query($link, 'SELECT * FROM test')) {
+ printf("[%03d][control string '%s'] [%d] %s.\n",
+ $offset + 2,
+ $control_string,
+ mysqli_errno($link),
+ mysqli_error($link));
+ return false;
+ }
+ while ($row = mysqli_fetch_assoc($res))
+ ;
+ mysqli_free_result($res);
+
+ clearstatcache();
+ if (!file_exists($trace_file)) {
+ printf("[%03d][control string '%s'] Trace file has not been written.\n",
+ $offset + 3,
+ $control_string,
+ gettype($tmp),
+ $tmp);
+ return false;
+ }
+
+ return trim(substr(file_get_contents($trace_file), 0, 100024));
+ }
+
+ $trace_file = sprintf('%s%s%s', sys_get_temp_dir(), DIRECTORY_SEPARATOR, 'mysqli_debug_phpt.trace');
+
+ $trace = try_control_string($link, 't:O,' . $trace_file, $trace_file, 10);
+ if (!strstr($trace, 'SELECT * FROM test') && !strstr($trace, 'mysql_real_query'))
+ printf("[015] SELECT query cannot be found in trace. Trace contents seems wrong.\n");
+
+ // T - gettimeofday() system call, system dependent format
+ // 16:57:03.350734 >mysql_real_query
+ $trace = try_control_string($link, 't:O,' . $trace_file . ':T', $trace_file, 20);
+ if (!preg_match('@^[012]{0,1}[0-9]{1}:[0-5]{0,1}[0-9]{1}:[0-5]{0,1}[0-9]{1}@ismU', $trace))
+ printf("[025] Timestamp not found. One reason could be that the test is borked and does not recognize the format of the gettimeofday() system call. Check manually (and fix the test, if needed :-)). First characters from trace are '%s'\n", substr($trace, 0, 80));
+
+ // i - add PID of the current process
+ // currently PHP is not multi-threaded, so it should be save to test for the PID of this PHP process
+ if (false === ($pid = getmypid()))
+ $pid = "[\d]+";
+
+ $trace = try_control_string($link, 't:O,' . $trace_file . ':i', $trace_file, 30);
+ if (!preg_match("@^" . $pid . "*@ismU", $trace))
+ printf("[035] Process ID has not been found, first characters from trace are '%s'\n", substr($trace, 0, 80));
+
+ // L - line numbers
+ $trace = try_control_string($link, 't:O,' . $trace_file . ':L', $trace_file, 40);
+ if (!preg_match("@^[\d]+@ismU", $trace))
+ printf("[045] Line numbers have not been found, first characters from trace are '%s'\n", substr($trace, 0, 80));
+
+ // F - file name
+ $trace = try_control_string($link, 't:O,' . $trace_file . ':F', $trace_file, 50);
+ // hopefully we'll never see a file name that's not covered by this regular expression...
+ if (!preg_match("@^\s*[/\w\\\\d\.\-]+\.[ch]@ismU", $trace))
+ printf("[055] File names seem to be missing, first characters from trace are '%s'\n", substr($trace, 0, 80));
+
+ // -n - print function nesting depth
+ $trace = try_control_string($link, 't:O,' . $trace_file . ':n', $trace_file, 60);
+ if (!preg_match("@^\d+:@ismU", $trace))
+ printf("[065] Nesting level seem to be missing, first characters from trace are '%s'\n", substr($trace, 0, 80));
+
+ // -t,[N] - maximum nesting level
+ $trace = try_control_string($link, 't,1:n:O,' . $trace_file, $trace_file, 70);
+ $lines = explode("\n", $trace);
+ foreach ($lines as $k => $line) {
+ $line = trim($line);
+ if (!preg_match("@^(\d+):+@ismU", $line, $matches)) {
+ printf("[075] Nesting level seem to be missing, first characters from trace are '%s'\n", substr($line, 0, 80));
+ } else {
+ if (!isset($matches[1]) || ((int)$matches[1] > 1)) {
+ printf("[076] Nesting level seem to be %d, should not be higher than 1, first characters from trace are '%s'\n",
+ $matches[1],
+ substr($line, 0, 80));
+ }
+ }
+ }
+
+ // omitting t
+ $trace = try_control_string($link, 'n:O,' . $trace_file, $trace_file, 80);
+ $lines = explode("\n", $trace);
+ foreach ($lines as $k => $line) {
+ $line = trim($line);
+ if (preg_match("@^[|\s]*>[\w]+@ism", $line, $matches)) {
+ printf("[085] Looks like a function call, but there should be none in the trace file, first characters from trace are '%s'\n",
+ substr($line, 0, 80));
+ }
+ }
+
+ // -f[,functions] - Limit debugger list to specified functions. Empty list -> all functions
+ $lines_all_funcs = explode("\n", try_control_string($link, 't:O,' . $trace_file, $trace_file, 90));
+ $functions_all_funcs = array();
+ foreach ($lines_all_funcs as $k => $line) {
+ $line = trim($line);
+ if (preg_match("@^[|\s]*>([\w:]+)@ism", $line, $matches)) {
+ $functions_all_funcs[$matches[1]] = $matches[1];
+ }
+ }
+
+ $lines_trace = explode("\n", try_control_string($link, 't:f:O,' . $trace_file, $trace_file, 100));
+ $functions_trace = array();
+ foreach ($lines_trace as $k => $line) {
+ $line = trim($line);
+ if (preg_match("@^[|\s]*>([\w:]+)@ism", $line, $matches)) {
+ $functions_trace[$matches[1]] = $matches[1];
+ }
+ }
+
+ $tmp = array_diff($functions_all_funcs, $functions_trace);
+ if (!empty($tmp)) {
+ printf("[105] Looks like not all functions are listed in the trace. Check manually, dumping diff.");
+ var_dump($tmp);
+ }
+
+ // get two or three function names to play with...
+ $test_functions = array('simple' => array(), 'doubledot' => array());
+
+ foreach ($functions_all_funcs as $func) {
+ if (count($test_functions['simple']) < 2 && !strstr($func, '::'))
+ $test_functions['simple'][$func] = $func;
+ else if (count($test_functions['doubledot']) < 2 && strstr($func, '::'))
+ $test_functions['doubledot'][$func] = $func;
+ }
+
+ $control_string = '';
+ if ($func = reset($test_functions['simple']))
+ $control_string .= sprintf('%s,', $func);
+ if ($func = reset($test_functions['doubledot']))
+ $control_string .= sprintf('%s,', $func);
+ if ($func = next($test_functions['simple']))
+ $control_string .= sprintf('%s,', $func);
+ if ($func = next($test_functions['doubledot']))
+ $control_string .= sprintf('%s,', $func);
+ $control_string = sprintf('t:f,%s:O,%s', $control_string, $trace_file);
+
+ $lines_trace = explode("\n", try_control_string($link, $control_string, $trace_file, 110));
+ $functions_trace = array();
+ foreach ($lines_trace as $k => $line) {
+ $line = trim($line);
+ if (preg_match("@^[|\s]*>([\w:]+)@ism", $line, $matches)) {
+ $functions_trace[$matches[1]] = $matches[1];
+ }
+ }
+
+ foreach ($test_functions['simple'] as $func)
+ if (isset($functions_trace[$func])) {
+ unset($functions_trace[$func]);
+ unset($test_functions['simple'][$func]);
+ }
+
+ foreach ($test_functions['doubledot'] as $func)
+ if (isset($functions_trace[$func])) {
+ unset($functions_trace[$func]);
+ unset($test_functions['doubledot'][$func]);
+ }
+
+ if (!empty($functions_trace)) {
+ printf("[115] Dumping list of unexpected functions which should have not been shown when using control string '%s'.\n",
+ $control_string);
+ var_dump($functions_trace);
+ }
+ $tmp = array_merge($test_functions['doubledot'], $test_functions['simple']);
+ if (!empty($tmp)) {
+ printf("[116] Dumping list of functions which should have been shown when using control string '%s'.\n",
+ $control_string);
+ var_dump($tmp);
+ }
+
+ if ($IS_MYSQLND) {
+ // mysqlnd only option
+ // m - trace memory allocations
+ $trace = try_control_string($link, 't:O,' . $trace_file . ':m', $trace_file, 120);
+ if (!preg_match("@^[|\s]*>\_mysqlnd_pefree@ismU", $trace, $matches) &&
+ !preg_match("@^[|\s]*>\_mysqlnd_pemalloc@ismU", $trace, $matches)) {
+ printf("[125] Memory dump does neither contain _mysqlnd_pefree nor _mysqlnd_pemalloc calls - check manually.\n");
+ var_dump($trace);
+ }
+
+ }
+
+ mysqli_close($link);
+ print "done";
+ if ($IS_MYSQLND)
+ print "libmysql/DBUG package prints some debug info here.";
+ @unlink($trace_file);
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+[083][control string 'n:O,%smysqli_debug_phpt.trace'] Trace file has not been written.
+done%s
diff --git a/ext/mysqli/tests/mysqli_debug_mysqlnd_only.phpt b/ext/mysqli/tests/mysqli_debug_mysqlnd_only.phpt
new file mode 100644
index 0000000..8ecf516
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_debug_mysqlnd_only.phpt
@@ -0,0 +1,128 @@
+--TEST--
+mysqli_debug() - mysqlnd only control strings
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+require_once('connect.inc');
+
+if (!function_exists('mysqli_debug'))
+ die("skip mysqli_debug() not available");
+
+if (!defined('MYSQLI_DEBUG_TRACE_ENABLED'))
+ die("skip: can't say for sure if mysqli_debug works");
+
+if (defined('MYSQLI_DEBUG_TRACE_ENABLED') && !MYSQLI_DEBUG_TRACE_ENABLED)
+ die("skip: debug functionality not enabled");
+
+if (!$IS_MYSQLND)
+ die("skip mysqlnd only test");
+?>
+--FILE--
+<?php
+ require_once('connect.inc');;
+ require_once('table.inc');
+
+ function try_control_string($link, $control_string, $trace_file, $offset) {
+
+ @unlink($trace_file);
+ if (true !== ($tmp = @mysqli_debug($control_string))) {
+ printf("[%03d][control string '%s'] Expecting boolean/true, got %s/%s.\n",
+ $offset + 1,
+ $control_string,
+ gettype($tmp),
+ $tmp);
+ return false;
+ }
+
+ if (!$res = mysqli_query($link, 'SELECT * FROM test')) {
+ printf("[%03d][control string '%s'] [%d] %s.\n",
+ $offset + 2,
+ $control_string,
+ mysqli_errno($link),
+ mysqli_error($link));
+ return false;
+ }
+ while ($row = mysqli_fetch_assoc($res))
+ ;
+ mysqli_free_result($res);
+
+ clearstatcache();
+ if (!file_exists($trace_file)) {
+ printf("[%03d][control string '%s'] Trace file has not been written.\n",
+ $offset + 3,
+ $control_string,
+ gettype($tmp),
+ $tmp);
+ return false;
+ }
+
+ return trim(substr(file_get_contents($trace_file), 0, 100024));
+ }
+
+ $memory_funcs = array(
+ '_mysqlnd_ecalloc',
+ '_mysqlnd_emalloc',
+ '_mysqlnd_palloc_free_thd_cache_reference',
+ '_mysqlnd_pecalloc',
+ '_mysqlnd_pefree',
+ '_mysqlnd_pemalloc',
+ '_mysqlnd_perealloc',
+ );
+ $trace_file = sprintf('%s%s%s', sys_get_temp_dir(), DIRECTORY_SEPARATOR, 'mysqli_debug_phpt.trace');
+
+ $trace = try_control_string($link, 't:m:O,' . $trace_file, $trace_file, 10);
+ if (!strstr($trace, 'SELECT * FROM test') && !strstr($trace, 'mysql_real_query'))
+ printf("[015] SELECT query cannot be found in trace. Trace contents seems wrong.\n");
+
+ $lines_trace = explode("\n", $trace);
+ $functions_trace = array();
+ foreach ($lines_trace as $k => $line) {
+ $line = trim($line);
+ if (preg_match("@^[|\s]*>([\w:]+)@ism", $line, $matches)) {
+ $functions_trace[$matches[1]] = $matches[1];
+ }
+ }
+
+ $found = 0;
+ foreach ($memory_funcs as $k => $name)
+ if (isset($functions_trace[$name]))
+ $found++;
+
+ if ($found < (count($memory_funcs) - 2))
+ printf("[016] Only %d memory functions have been found, expecting at least %d.\n",
+ $found, count($memory_funcs) - 2);
+
+ $trace = try_control_string($link, 't:O,' . $trace_file, $trace_file, 20);
+ if (!strstr($trace, 'SELECT * FROM test') && !strstr($trace, 'mysql_real_query'))
+ printf("[025] SELECT query cannot be found in trace. Trace contents seems wrong.\n");
+
+ $lines_trace = explode("\n", $trace);
+ $functions_trace = array();
+ foreach ($lines_trace as $k => $line) {
+ $line = trim($line);
+ if (preg_match("@^[|\s]*>([\w:]+)@ism", $line, $matches)) {
+ $functions_trace[$matches[1]] = $matches[1];
+ }
+ }
+
+ $found = 0;
+ foreach ($memory_funcs as $k => $name)
+ if (isset($functions_trace[$name]))
+ $found++;
+
+ if ($found > 2)
+ printf("[026] More than %d memory functions have been recorded, that's strange.\n",
+ $found);
+
+ mysqli_close($link);
+ @unlink($trace_file);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_disable_reads_from_master.phpt b/ext/mysqli/tests/mysqli_disable_reads_from_master.phpt
new file mode 100644
index 0000000..9814c6e
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_disable_reads_from_master.phpt
@@ -0,0 +1,47 @@
+--TEST--
+mysqli_disable_reads_from_master()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+if (!function_exists('mysqli_disable_reads_from_master')) {
+ die("skip mysqli_disable_reads_from_master() not available");
+}
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (NULL !== ($tmp = @mysqli_disable_reads_from_master()))
+ printf("[001] Expecting NULL/NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (NULL !== ($tmp = @mysqli_disable_reads_from_master($link)))
+ printf("[002] Expecting NULL/NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ printf("[003] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+ }
+
+ if (!is_bool($tmp = mysqli_disable_reads_from_master($link)))
+ printf("[004] Expecting boolean/[true|false] value, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_close($link);
+
+ if (NULL !== ($tmp = mysqli_disable_reads_from_master($link)))
+ printf("[005] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Warning: mysqli_disable_reads_from_master(): Couldn't fetch mysqli in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_driver.phpt b/ext/mysqli/tests/mysqli_driver.phpt
new file mode 100644
index 0000000..4e266a0
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_driver.phpt
@@ -0,0 +1,114 @@
+--TEST--
+mysqli_driver class
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require("table.inc");
+
+ if (!is_object($driver = new mysqli_driver()))
+ printf("[001] Failed to create mysqli_driver object\n");
+
+ $client_info = mysqli_get_client_info();
+ if (($tmp = $driver->client_info) !== $client_info)
+ printf("[002] Expecting %s/%s, got %s/%s\n",
+ gettype($client_info), $client_info,
+ gettype($tmp), $tmp);
+
+ $client_version = mysqli_get_client_version();
+ if (($tmp = $driver->client_version) !== $client_version)
+ printf("[003] Expecting %s/%s, got %s/%s\n",
+ gettype($client_version), $client_version,
+ gettype($tmp), $tmp);
+
+ if (!is_int($tmp = $driver->driver_version) || (0 == $tmp))
+ printf("[004] Expecting int/any, got %s/%s\n",
+ gettype($tmp), $tmp);
+
+
+ $all_modes = array(MYSQLI_REPORT_INDEX, MYSQLI_REPORT_ERROR, MYSQLI_REPORT_STRICT,
+ MYSQLI_REPORT_ALL, MYSQLI_REPORT_OFF);
+ $report_mode = $driver->report_mode;
+ if (!is_int($report_mode))
+ printf("[005] Expecting int/any, got %s/%s\n",
+ gettype($report_mode), $report_mode);
+
+ if (!in_array($report_mode, $all_modes))
+ printf("[006] Illegal report mode returned? Got %s, expected %s\n",
+ $report_mode, implode(', ', $all_modes));
+
+ $driver->report_mode = MYSQLI_REPORT_STRICT;
+ $ok = false;
+ try {
+
+ if ($link = my_mysqli_connect($host, $user . 'unknown_really', $passwd . 'non_empty', $db, $port, $socket))
+ printf("[007] Can connect to the server using host=%s, user=%s, passwd=***non_empty, dbname=%s, port=%s, socket=%s\n",
+ $host, $user . 'unknown_really', $db, $port, $socket);
+ mysqli_close($link);
+
+ } catch (mysqli_sql_exception $e) {
+ $ok = true;
+ if ('' == $e->getMessage())
+ printf("[008] getMessage() has returned an emptry string.\n");
+ if ('' == $e->getCode())
+ printf("[009] getCode() has returned an empty string.\n");
+ if ('' == $e->getFile())
+ printf("[010] getFile() has returned an empty string.\n");
+ if ('' == $e->getLine())
+ printf("[011] getLine() has returned an empty string.\n");
+ $tmp = $e->getTrace();
+ if (empty($tmp))
+ printf("[012] getTrace() has returned an empty array.\n");
+ if ('' == $e->getTraceAsString())
+ printf("[013] getTraceAsString() has returned an empty string.\n");
+ if ('' == $e->__toString())
+ printf("[014] __toString() has returned an empty string.\n");
+
+ }
+ if (!$ok)
+ printf("[015] Error reporting mode has not been switched to exceptions and or no exception thrown\n");
+
+
+ $driver->report_mode = MYSQLI_REPORT_OFF;
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[016] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+ mysqli_query($link, "NO_SQL");
+ mysqli_close($link);
+
+ $driver->report_mode = MYSQLI_REPORT_ERROR;
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[017] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+ mysqli_query($link, "NO_SQL");
+ mysqli_close($link);
+
+ if (MYSQLI_REPORT_ERROR !== $driver->report_mode)
+ printf("[018] Error mode should be different\n");
+
+ /* TODO - more report testing should go in here, but it's not really documented what behaviour is expected */
+
+ $driver->report_mode = $report_mode;
+
+ $reconnect = $driver->reconnect;
+ if (!is_bool($reconnect))
+ printf("[019] Expecting boolean/any, got %s/%s\n",
+ gettype($reconnect), $reconnect);
+
+ /* pointless, but I need more documentation */
+ $driver->reconnect = true;
+ $driver->reconnect = false;
+ $driver->reconnect = $reconnect;
+
+ if (!is_bool($embedded = $driver->embedded))
+ printf("[020] Expecting boolean/any, got %s/%s\n",
+ gettype($embedded), $embedded);
+
+ print "done!";
+?>
+--EXPECTF--
+Warning: mysqli_query(): (%d/%d): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'NO_SQL' at line 1 in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_driver_unclonable.phpt b/ext/mysqli/tests/mysqli_driver_unclonable.phpt
new file mode 100644
index 0000000..0e2438e
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_driver_unclonable.phpt
@@ -0,0 +1,13 @@
+--TEST--
+Trying to clone mysqli_driver object
+--SKIPIF--
+<?php require_once('skipif.inc'); ?>
+<?php require_once('skipifemb.inc'); ?>
+--FILE--
+<?php
+ $driver = new mysqli_driver;
+ $driver_clone = clone $driver;
+ print "done!";
+?>
+--EXPECTF--
+Fatal error: Trying to clone an uncloneable object of class mysqli_driver in %s on line %d \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_dump_debug_info.phpt b/ext/mysqli/tests/mysqli_dump_debug_info.phpt
new file mode 100644
index 0000000..bd87ddf
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_dump_debug_info.phpt
@@ -0,0 +1,44 @@
+--TEST--
+mysqli_dump_debug_info()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (NULL !== ($tmp = @mysqli_dump_debug_info()))
+ printf("[001] Expecting NULL/NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (NULL !== ($tmp = @mysqli_dump_debug_info($link)))
+ printf("[002] Expecting NULL/NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ printf("[003] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+ exit(1);
+ }
+
+ if (!is_bool($tmp = mysqli_dump_debug_info($link)))
+ printf("[004] Expecting boolean/[true|false] value, got %s/%s, [%d] %s\n",
+ gettype($tmp), $tmp,
+ mysqli_errno($link), mysqli_error($link));
+
+ mysqli_close($link);
+
+ if (NULL !== ($tmp = mysqli_dump_debug_info($link)))
+ printf("[005] Expecting NULL, got %s/%s\n",
+ gettype($tmp), $tmp,
+ mysqli_errno($link), mysqli_error($link));
+
+ print "done!";
+?>
+--EXPECTF--
+Warning: mysqli_dump_debug_info(): Couldn't fetch mysqli in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_dump_debug_info_oo.phpt b/ext/mysqli/tests/mysqli_dump_debug_info_oo.phpt
new file mode 100644
index 0000000..82edef5
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_dump_debug_info_oo.phpt
@@ -0,0 +1,38 @@
+--TEST--
+mysqli_dump_debug_info()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!$mysqli = new mysqli($host, $user, $passwd, $db, $port, $socket))
+ printf("[001] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n", $host, $user, $db, $port, $socket);
+
+ if (NULL !== ($tmp = @$mysqli->dump_debug_info($link)))
+ printf("[002] Expecting NULL/NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_bool($tmp = $mysqli->dump_debug_info()))
+ printf("[003] Expecting boolean/[true|false] value, got %s/%s, [%d] %s\n",
+ gettype($tmp), $tmp,
+ $mysqli->errno, $mysqli->error);
+
+ $mysqli->close();
+
+ if (NULL !== ($tmp = $mysqli->dump_debug_info()))
+ printf("[004] Expecting NULL, got %s/%s, [%d] %s\n",
+ gettype($tmp), $tmp,
+ $mysqli->errno, $mysqli->error);
+
+ print "done!";
+?>
+--EXPECTF--
+Warning: mysqli::dump_debug_info(): Couldn't fetch mysqli in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_embedded_connect.phpt b/ext/mysqli/tests/mysqli_embedded_connect.phpt
new file mode 100644
index 0000000..37891f5
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_embedded_connect.phpt
@@ -0,0 +1,32 @@
+--TEST--
+mysqli_embedded_connect()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifnotemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+ $tmp = NULL;
+ $link = NULL;
+
+ if (NULL !== ($tmp = @mysqli_embedded_connect()))
+ printf("[001] Expecting NULL/NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$link = mysqli_embedded_connect($db)) {
+ printf("[002] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+ }
+
+ if (!is_bool($tmp = mysqli_embedded_connect($db . '_unknown')))
+ printf("[003] Expecting boolean/[true|false] value, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_close($link);
+
+ print "done!";
+?>
+--EXPECTF--
+Warning: mysqli_embedded_connect() expects parameter 1 to be mysqli, null given in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_enable_reads_from_master.phpt b/ext/mysqli/tests/mysqli_enable_reads_from_master.phpt
new file mode 100644
index 0000000..e23ddd1
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_enable_reads_from_master.phpt
@@ -0,0 +1,43 @@
+--TEST--
+mysqli_enable_reads_from_master()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+if (!function_exists('mysqli_enable_reads_from_master')) {
+ die("skip function mysqli_enable_reads_from_master() not available\n");
+}
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (NULL !== ($tmp = @mysqli_enable_reads_from_master()))
+ printf("[001] Expecting NULL/NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (NULL !== ($tmp = @mysqli_enable_reads_from_master($link)))
+ printf("[002] Expecting NULL/NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ printf("[003] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+ }
+
+ if (!is_bool($tmp = mysqli_enable_reads_from_master($link)))
+ printf("[004] Expecting boolean/[true|false] value, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_close($link);
+
+ if (NULL !== ($tmp = mysqli_enable_reads_from_master($link)))
+ printf("[005] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--EXPECTF--
+Warning: mysqli_enable_reads_from_master(): Couldn't fetch mysqli in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_errno.phpt b/ext/mysqli/tests/mysqli_errno.phpt
new file mode 100644
index 0000000..0e9f049
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_errno.phpt
@@ -0,0 +1,52 @@
+--TEST--
+mysqli_errno()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_errno()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_errno($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ printf("[003] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+}
+
+ var_dump(mysqli_errno($link));
+
+ if (!mysqli_query($link, 'DROP TABLE IF EXISTS test')) {
+ printf("[004] Failed to drop old test table: [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ mysqli_query($link, 'SELECT * FROM test');
+ var_dump(mysqli_errno($link));
+
+ @mysqli_query($link, 'No SQL');
+ if (($tmp = mysqli_errno($link)) == 0)
+ printf("[005] Expecting int/any non zero got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_close($link);
+
+ var_dump(mysqli_errno($link));
+
+ print "done!";
+?>
+--EXPECTF--
+int(0)
+int(%d)
+
+Warning: mysqli_errno(): Couldn't fetch mysqli in %s on line %d
+NULL
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_errno_oo.phpt b/ext/mysqli/tests/mysqli_errno_oo.phpt
new file mode 100644
index 0000000..5d5ea25
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_errno_oo.phpt
@@ -0,0 +1,49 @@
+--TEST--
+$mysqli->errno
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ $mysqli = new mysqli();
+ if (0 !== ($tmp = @$mysqli->errno))
+ printf("[001] Expecting int/0, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$mysqli = new mysqli($host, $user, $passwd, $db, $port, $socket))
+ printf("[002] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ var_dump($mysqli->errno);
+
+ if (!$mysqli->query('DROP TABLE IF EXISTS test')) {
+ printf("[003] Failed to drop old test table: [%d] %s\n", $mysqli->errno, $mysqli->error);
+ }
+
+ $mysqli->query('SELECT * FROM test');
+ var_dump($mysqli->errno);
+
+ @$mysqli->query('No SQL');
+ if (($tmp = $mysqli->errno) === 0)
+ printf("[004] Expecting int/any non zero got %s/%s\n", gettype($tmp), $tmp);
+
+ $mysqli->close();
+
+ var_dump($mysqli->errno);
+
+ print "done!";
+?>
+--EXPECTF--
+int(0)
+int(%d)
+
+Warning: main(): Couldn't fetch mysqli in %s on line %d
+NULL
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_error.phpt b/ext/mysqli/tests/mysqli_error.phpt
new file mode 100644
index 0000000..5e70d59
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_error.phpt
@@ -0,0 +1,49 @@
+--TEST--
+mysqli_error()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_error()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_error($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ printf("[003] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+ }
+
+ $tmp = mysqli_error($link);
+ if (!is_string($tmp) || ('' !== $tmp))
+ printf("[004] Expecting string/empty, got %s/%s. [%d] %s\n", gettype($tmp), $tmp, mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, 'DROP TABLE IF EXISTS test')) {
+ printf("[005] Failed to drop old test table: [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ mysqli_query($link, 'SELECT * FROM test');
+ $tmp = mysqli_error($link);
+ if (!is_string($tmp) || !preg_match("/Table '\w*\.test' doesn't exist/su", $tmp))
+ printf("[006] Expecting string/[Table... doesn't exit], got %s/%s. [%d] %s\n", gettype($tmp), $tmp, mysqli_errno($link), mysqli_error($link));
+
+ mysqli_close($link);
+
+ var_dump(mysqli_error($link));
+
+ print "done!";
+?>
+--EXPECTF--
+Warning: mysqli_error(): Couldn't fetch mysqli in %s on line %d
+NULL
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_error_oo.phpt b/ext/mysqli/tests/mysqli_error_oo.phpt
new file mode 100644
index 0000000..1f05896
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_error_oo.phpt
@@ -0,0 +1,46 @@
+--TEST--
+$mysqli->error
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ $mysqli = new mysqli();
+ if ('' !== ($tmp = @$mysqli->error))
+ printf("[001] Expecting empty string, got %s/'%s'\n", gettype($tmp), $tmp);
+
+ if (!$mysqli = new mysqli($host, $user, $passwd, $db, $port, $socket))
+ printf("[002] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ $tmp = $mysqli->error;
+ if (!is_string($tmp) || ('' !== $tmp))
+ printf("[003] Expecting string/empty, got %s/%s. [%d] %s\n", gettype($tmp), $tmp, $mysqli->errno, $mysqli->error);
+
+ if (!$mysqli->query('DROP TABLE IF EXISTS test')) {
+ printf("[004] Failed to drop old test table: [%d] %s\n", $mysqli->errno, $mysqli->error);
+ }
+
+ $mysqli->query('SELECT * FROM test');
+ $tmp = $mysqli->error;
+ if (!is_string($tmp) || !preg_match("/Table '\w*\.test' doesn't exist/su", $tmp))
+ printf("[006] Expecting string/[Table... doesn't exit], got %s/%s. [%d] %s\n", gettype($tmp), $tmp, $mysqli->errno, $mysqli->error);
+
+ $mysqli->close();
+
+ var_dump($mysqli->error);
+
+ print "done!";
+?>
+--EXPECTF--
+Warning: main(): Couldn't fetch mysqli in %s on line %d
+NULL
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_error_unicode.phpt b/ext/mysqli/tests/mysqli_error_unicode.phpt
new file mode 100644
index 0000000..b59ed5f
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_error_unicode.phpt
@@ -0,0 +1,51 @@
+--TEST--
+mysqli_error()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_error()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_error($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ printf("[003] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+ }
+
+ if (!(version_compare(PHP_VERSION, '5.9.9', '>') == 1)) {
+ mysqli_query($link, "set names utf8");
+ }
+
+ $tmp = mysqli_error($link);
+ if (!is_string($tmp) || ('' !== $tmp))
+ printf("[004] Expecting string/empty, got %s/%s. [%d] %s\n", gettype($tmp), $tmp, mysqli_errno($link), mysqli_error($link));
+
+
+ mysqli_query($link, 'SELECT * FROM нÑма_такава_таблица');
+ $tmp = mysqli_error($link);
+ var_dump(str_replace($db.".", "", $tmp));
+
+ mysqli_close($link);
+
+ var_dump(mysqli_error($link));
+
+ print "done!";
+?>
+--EXPECTF--
+%unicode|string%(%d) "Table 'нÑма_такава_таблица' doesn't exist"
+
+Warning: mysqli_error(): Couldn't fetch mysqli in %s on line %d
+NULL
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_expire_password.phpt b/ext/mysqli/tests/mysqli_expire_password.phpt
new file mode 100644
index 0000000..ce89a21
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_expire_password.phpt
@@ -0,0 +1,145 @@
+--TEST--
+MySQL 5.6 EXPIRE PASSWORD protocol change
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('connect.inc');
+
+if ($IS_MYSQLND && !version_compare(PHP_VERSION, '5.4.12-dev', ">=")) {
+ die("SKIP Available in mysqlnd as of PHP 5.4.12-dev");
+}
+
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ die(sprintf("SKIP Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket));
+}
+
+if ($link->server_version < 50610)
+ die(sprintf("SKIP Needs MySQL 5.6.10 or newer, found MySQL %s\n", $link->server_info));
+
+if (!$IS_MYSQLND && (mysqli_get_client_version() < 50610)) {
+ die(sprintf("SKIP Needs libmysql 5.6.10 or newer, found %s\n", mysqli_get_client_version()));
+}
+
+mysqli_query($link, 'DROP USER expiretest');
+mysqli_query($link, 'DROP USER expiretest@localhost');
+
+if (!mysqli_query($link, 'CREATE USER expiretest@"%"') ||
+ !mysqli_query($link, 'CREATE USER expiretest@"localhost"')) {
+ printf("skip Cannot create second DB user [%d] %s", mysqli_errno($link), mysqli_error($link));
+ mysqli_close($link);
+ die("skip CREATE USER failed");
+}
+
+if (!mysqli_query($link, 'ALTER USER expiretest@"%" PASSWORD EXPIRE') ||
+ !mysqli_query($link, 'ALTER USER expiretest@"localhost" PASSWORD EXPIRE')) {
+ printf("skip Cannot modify second DB user [%d] %s", mysqli_errno($link), mysqli_error($link));
+ mysqli_close($link);
+ die("skip ALTER USER failed");
+}
+
+if (!$link->query("DROP TABLE IF EXISTS test") ||
+ !$link->query("CREATE TABLE test (id INT)") || !$link->query("INSERT INTO test(id) VALUES (1)"))
+ die(sprintf("SKIP [%d] %s\n", $link->errno, $link->error));
+
+
+
+if (!mysqli_query($link, sprintf("GRANT SELECT ON TABLE %s.test TO expiretest@'%%'", $db)) ||
+ !mysqli_query($link, sprintf("GRANT SELECT ON TABLE %s.test TO expiretest@'localhost'", $db))) {
+ printf("skip Cannot grant SELECT to user [%d] %s", mysqli_errno($link), mysqli_error($link));
+ mysqli_close($link);
+ die("skip GRANT failed");
+}
+?>
+--FILE--
+<?php
+ require_once('connect.inc');
+ require_once('table.inc');
+
+ /* default */
+ if (!$link = my_mysqli_connect($host, 'expiretest', "", $db, $port, $socket)) {
+ printf("[001] Cannot connect [%d] %s\n",
+ mysqli_connect_errno(), mysqli_connect_error());
+ } else {
+ $link->query("SELECT id FROM test WHERE id = 1");
+ printf("[002] Connect should fail, [%d] %s\n", $link->errno, $link->error);
+ }
+
+ /* explicitly requesting default */
+ $link = mysqli_init();
+ $link->options(MYSQLI_OPT_CAN_HANDLE_EXPIRED_PASSWORDS, 0);
+ if (!my_mysqli_real_connect($link, $host, 'expiretest', "", $db, $port, $socket)) {
+ printf("[003] Cannot connect [%d] %s\n",
+ mysqli_connect_errno(), mysqli_connect_error());
+ } else {
+ $link->query("SELECT id FROM test WHERE id = 1");
+ printf("[004] Connect should fail, [%d] %s\n", $link->errno, $link->error);
+ }
+
+ /* allow connect */
+ $link = mysqli_init();
+ $link->options(MYSQLI_OPT_CAN_HANDLE_EXPIRED_PASSWORDS, 1);
+ if (!my_mysqli_real_connect($link, $host, 'expiretest', "", $db, $port, $socket)) {
+ printf("[005] Cannot connect [%d] %s\n",
+ mysqli_connect_errno(), mysqli_connect_error());
+ } else {
+ $link->query("SELECT id FROM test WHERE id = 1");
+ printf("[006] Connect allowed, query fail, [%d] %s\n", $link->errno, $link->error);
+ $link->close();
+ }
+
+ /* allow connect, fix pw */
+ $link = mysqli_init();
+ $link->options(MYSQLI_OPT_CAN_HANDLE_EXPIRED_PASSWORDS, 1);
+ if (!my_mysqli_real_connect($link, $host, 'expiretest', "", $db, $port, $socket)) {
+ printf("[007] Cannot connect [%d] %s\n",
+ mysqli_connect_errno(), mysqli_connect_error());
+ } else {
+ $link->query("SET PASSWORD=PASSWORD('expiretest')");
+ printf("[008] Connect allowed, pw set, [%d] %s\n", $link->errno, $link->error);
+ if ($res = $link->query("SELECT id FROM test WHERE id = 1"))
+ var_dump($res->fetch_assoc());
+ $link->close();
+ }
+
+
+ /* check login */
+ if (!$link = my_mysqli_connect($host, 'expiretest', "expiretest", $db, $port, $socket)) {
+ printf("[001] Cannot connect [%d] %s\n",
+ mysqli_connect_errno(), mysqli_connect_error());
+ } else {
+ $link->query("SELECT id FROM test WHERE id = 1");
+ if ($res = $link->query("SELECT id FROM test WHERE id = 1"))
+ var_dump($res->fetch_assoc());
+ $link->close();
+ }
+
+
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+ mysqli_query($link, 'DROP USER expiretest');
+ mysqli_query($link, 'DROP USER expiretest@localhost');
+?>
+--EXPECTF--
+
+Warning: mysqli_real_connect(): (HY000/1820): %s in %s on line %d
+[001] Cannot connect [1820] %s
+
+Warning: mysqli_real_connect(): (HY000/1820): %s in %s on line %d
+[003] Cannot connect [1820] %s
+[006] Connect allowed, query fail, [1820] %s
+[008] Connect allowed, pw set, [0%A
+array(1) {
+ ["id"]=>
+ string(1) "1"
+}
+array(1) {
+ ["id"]=>
+ string(1) "1"
+}
+done!
diff --git a/ext/mysqli/tests/mysqli_explain_metadata.phpt b/ext/mysqli/tests/mysqli_explain_metadata.phpt
new file mode 100644
index 0000000..fc1f9db
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_explain_metadata.phpt
@@ -0,0 +1,162 @@
+--TEST--
+EXPLAIN - metadata
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+require_once("connect.inc");
+if (!$IS_MYSQLND)
+ die("skip Open libmysql/MySQL issue http://bugs.mysql.com/?id=62350");
+?>
+--FILE--
+<?php
+ require_once('connect.inc');
+ require_once('table.inc');
+
+ if (!$res = mysqli_query($link, 'EXPLAIN SELECT t1.*, t2.* FROM test AS t1, test AS t2'))
+ printf("[001] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $num_rows = 0;
+ $num_fields = 0;
+ $field_names = array();
+ if (!$row = mysqli_fetch_assoc($res)) {
+ printf("[002] Expecting result but got no data [%d] %s\n",
+ mysqli_errno($link), mysqli_error($link));
+ } else {
+ $num_rows++;
+ $num_fields = count($row);
+ foreach ($row as $name => $value)
+ $field_names[$name] = gettype($value);
+ }
+
+ while ($row = mysqli_fetch_assoc($res))
+ $num_rows++;
+
+ if (($tmp = mysqli_num_rows($res)) !== $num_rows) {
+ printf("[003] Expecting int/%d got %s/%s\n",
+ $num_rows, gettype($tmp), $tmp);
+ }
+ if (($tmp = mysqli_field_count($link)) !== $num_fields) {
+ printf("[004] Expecting int/%d got %s/%s\n",
+ $num_fields, gettype($tmp), $tmp);
+ }
+ $fields = mysqli_fetch_fields($res);
+ if (($tmp = count($fields)) !== $num_fields) {
+ printf("[005] Expecting int/%d got %s/%s\n",
+ $num_fields, gettype($tmp), $tmp);
+ }
+
+ foreach ($fields as $k => $field) {
+ $field->max_length = 0;// change it or we will get diff error
+ if (isset($field_names[$field->name])) {
+ unset($field_names[$field->name]);
+ } else {
+ printf("[006] Unexpected field '%s', dumping info\n");
+ var_dump($field);
+ }
+ }
+ if (!empty($field_names)) {
+ printf("[007] Field descriptions missing for the following columns\n");
+ var_dump($field_names);
+ }
+
+ mysqli_free_result($res);
+
+ $stmt = mysqli_stmt_init($link);
+ /* Depending on your version, the MySQL server migit not support this */
+ if ($stmt->prepare('EXPLAIN SELECT t1.*, t2.* FROM test AS t1, test AS t2') && $stmt->execute()) {
+ if (!mysqli_stmt_store_result($stmt))
+ printf("[008] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!$res_meta = mysqli_stmt_result_metadata($stmt))
+ printf("[009] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (($tmp = mysqli_stmt_num_rows($stmt)) !== $num_rows) {
+ printf("[010] Expecting int/%d got %s/%s\n",
+ $num_rows, gettype($tmp), $tmp);
+ }
+ if (($tmp = mysqli_stmt_field_count($stmt)) !== $num_fields) {
+ printf("[011] Expecting int/%d got %s/%s\n",
+ $num_fields, gettype($tmp), $tmp);
+ }
+ if (($tmp = mysqli_field_count($link)) !== $num_fields) {
+ printf("[013] Expecting int/%d got %s/%s\n",
+ $num_fields, gettype($tmp), $tmp);
+ }
+ if (($tmp = $res_meta->field_count) !== $num_fields) {
+ printf("[014] Expecting int/%d got %s/%s\n",
+ $num_fields, gettype($tmp), $tmp);
+ }
+ $fields_res_meta = mysqli_fetch_fields($res_meta);
+ if (($tmp = count($fields_res_meta)) !== $num_fields)
+ printf("[015] Expecting int/%d got %s/%s\n",
+ $num_fields, gettype($tmp), $tmp);
+
+ if ($fields_res_meta != $fields) {
+ printf("[016] Prepared Statement metadata differs from normal metadata, dumping\n");
+ var_dump($fields_res_meta);
+ var_dump($fields);
+ }
+
+ if (function_exists('mysqli_stmt_get_result') &&
+ $stmt->prepare('EXPLAIN SELECT t1.*, t2.* FROM test AS t1, test AS t2') &&
+ $stmt->execute()) {
+ if (!$res_stmt = mysqli_stmt_get_result($stmt)) {
+ printf("[017] Cannot fetch result from PS [%d] %s\n",
+ mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ }
+ if (($tmp = mysqli_num_rows($res_stmt)) !== $num_rows) {
+ printf("[018] Expecting int/%d got %s/%s\n",
+ $num_rows, gettype($tmp), $tmp);
+ }
+ if ((mysqli_stmt_num_rows($stmt)) !== 0) {
+ printf("[019] Expecting int/0 got %s/%s\n", gettype($tmp), $tmp);
+ }
+ if (($tmp = mysqli_stmt_field_count($stmt)) !== $num_fields) {
+ printf("[020] Expecting int/%d got %s/%s\n",
+ $num_fields, gettype($tmp), $tmp);
+
+ }
+ if (($tmp = $res_stmt->field_count) !== $num_fields) {
+ printf("[021] Expecting int/%d got %s/%s\n",
+ $num_fields, gettype($tmp), $tmp);
+ }
+
+ $fields_stmt = mysqli_fetch_fields($res_stmt);
+ if (($tmp = count($fields_stmt)) !== $num_fields) {
+ printf("[022] Expecting int/%d got %s/%s\n",
+ $num_fields, gettype($tmp), $tmp);
+ }
+ reset($fields);
+ foreach ($fields_stmt as $fields_stmt_val) {
+ list(,$fields_val) = each($fields);
+ unset($fields_stmt_val->max_length);
+ unset($fields_val->max_length);
+ if ($fields_stmt_val != $fields_val) {
+ printf("[023] PS mysqli_stmt_get_result() metadata seems wrong, dumping\n");
+ var_dump($fields_stmt_val);
+ var_dump($fields_val);
+ }
+ }
+/*
+ if ($fields_stmt != $fields) {
+ printf("[023] PS mysqli_stmt_get_result() metadata seems wrong, dumping\n");
+ var_dump($fields_stmt);
+ var_dump($fields);
+ }
+*/
+ mysqli_free_result($res_stmt);
+ }
+ }
+ mysqli_stmt_close($stmt);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+done!
diff --git a/ext/mysqli/tests/mysqli_fetch_all.phpt b/ext/mysqli/tests/mysqli_fetch_all.phpt
new file mode 100644
index 0000000..63b6ad2
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_fetch_all.phpt
@@ -0,0 +1,440 @@
+--TEST--
+mysqli_fetch_all()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+if (!function_exists('mysqli_fetch_all'))
+ die("skip: function only available with mysqlnd");
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_fetch_all()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_fetch_all($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+ if (!$res = mysqli_query($link, "SELECT * FROM test ORDER BY id LIMIT 2")) {
+ printf("[004] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ print "[005]\n";
+ var_dump(mysqli_fetch_all($res));
+ mysqli_free_result($res);
+
+ if (!$res = mysqli_query($link, "SELECT * FROM test ORDER BY id LIMIT 2")) {
+ printf("[006] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ print "[007]\n";
+ var_dump(mysqli_fetch_all($res, MYSQLI_NUM));
+ mysqli_free_result($res);
+
+ if (!$res = mysqli_query($link, "SELECT * FROM test ORDER BY id LIMIT 2")) {
+ printf("[008] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ print "[008]\n";
+ var_dump(mysqli_fetch_all($res, MYSQLI_BOTH));
+ mysqli_free_result($res);
+
+ if (!$res = mysqli_query($link, "SELECT * FROM test ORDER BY id LIMIT 2")) {
+ printf("[009] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ print "[010]\n";
+ var_dump(mysqli_fetch_all($res, MYSQLI_ASSOC));
+
+ print "[011]\n";
+ var_dump(mysqli_fetch_all($res));
+ mysqli_free_result($res);
+
+ if (!$res = mysqli_query($link, "SELECT * FROM test ORDER BY id LIMIT 2")) {
+ printf("[012] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ print "[013]\n";
+ var_dump(mysqli_fetch_all($res, MYSQLI_ASSOC));
+
+ print "[016]\n";
+ var_dump(mysqli_fetch_all($res));
+
+ if (!$res = mysqli_query($link, "SELECT 1 AS a, 2 AS a, 3 AS c, 4 AS C, NULL AS d, true AS e")) {
+ printf("[010] Cannot run query, [%d] %s\n", mysqli_errno($link), $mysqli_error($link));
+ }
+ print "[017]\n";
+ var_dump(mysqli_fetch_all($res, MYSQLI_BOTH));
+
+ mysqli_free_result($res);
+ if (!$res = mysqli_query($link, "SELECT 1 AS a, 2 AS b, 3 AS c, 4 AS C")) {
+ printf("[018] Cannot run query, [%d] %s\n",
+ mysqli_errno($link), $mysqli_error($link));
+ exit(1);
+ }
+
+ do {
+ $illegal_mode = mt_rand(-10000, 10000);
+ } while (in_array($illegal_mode, array(MYSQLI_ASSOC, MYSQLI_NUM, MYSQLI_BOTH)));
+ // NOTE: for BC reasons with ext/mysql, ext/mysqli accepts invalid result modes.
+ $tmp = mysqli_fetch_all($res, $illegal_mode);
+ if (false !== $tmp)
+ printf("[019] Expecting boolean/false although, got %s/%s. [%d] %s\n",
+ gettype($tmp), $tmp, mysqli_errno($link), mysqli_error($link));
+
+ mysqli_free_result($res);
+
+ function func_mysqli_fetch_all($link, $engine, $sql_type, $sql_value, $php_value, $offset, $regexp_comparison = NULL) {
+
+ if (!mysqli_query($link, "DROP TABLE IF EXISTS test")) {
+ printf("[%04d] [%d] %s\n", $offset, mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ if (!mysqli_query($link, $sql = sprintf("CREATE TABLE test(id INT NOT NULL, label %s, PRIMARY KEY(id)) ENGINE = %s", $sql_type, $engine))) {
+ // don't bail, engine might not support the datatype
+ return false;
+ }
+
+ if (is_null($php_value)) {
+ if (!mysqli_query($link, $sql = sprintf("INSERT INTO test(id, label) VALUES (1, NULL)"))) {
+ printf("[%04d] [%d] %s\n", $offset + 1, mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+ } else {
+ if (is_string($sql_value)) {
+ if (!mysqli_query($link, $sql = "INSERT INTO test(id, label) VALUES (1, '" . $sql_value . "')")) {
+ printf("[%04ds] [%d] %s - %s\n", $offset + 1, mysqli_errno($link), mysqli_error($link), $sql);
+ return false;
+ }
+ } else {
+ if (!mysqli_query($link, $sql = sprintf("INSERT INTO test(id, label) VALUES (1, '%d')", $sql_value))) {
+ printf("[%04di] [%d] %s\n", $offset + 1, mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+ }
+ }
+
+ if (!$res = mysqli_query($link, "SELECT id, label FROM test")) {
+ printf("[%04d] [%d] %s\n", $offset + 2, mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ if (!$tmp = mysqli_fetch_all($res, MYSQLI_BOTH)) {
+ printf("[%04d] [%d] %s\n", $offset + 3, mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+ $row = $tmp[0];
+
+ $fields = mysqli_fetch_fields($res);
+
+ if (!(gettype($php_value)=="unicode" && ($fields[1]->flags & 128))) {
+
+ if ($regexp_comparison) {
+ if (!preg_match($regexp_comparison, (string)$row['label']) || !preg_match($regexp_comparison, (string)$row[1])) {
+ printf("[%04d] Expecting %s/%s [reg exp = %s], got %s/%s resp. %s/%s. [%d] %s\n", $offset + 4,
+ gettype($php_value), $php_value, $regexp_comparison,
+ gettype($row[1]), $row[1],
+ gettype($row['label']), $row['label'], mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+ } else {
+ if (($row['label'] !== $php_value) || ($row[1] != $php_value)) {
+ printf("[%04d] Expecting %s/%s, got %s/%s resp. %s/%s. [%d] %s\n", $offset + 4,
+ gettype($php_value), $php_value,
+ gettype($row[1]), $row[1],
+ gettype($row['label']), $row['label'], mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ function func_mysqli_fetch_array_make_string($len) {
+
+ $ret = '';
+ for ($i = 0; $i < $len; $i++)
+ $ret .= chr(mt_rand(65, 90));
+
+ return $ret;
+ }
+
+ func_mysqli_fetch_all($link, $engine, "TINYINT", -11, "-11", 20);
+ func_mysqli_fetch_all($link, $engine, "TINYINT", NULL, NULL, 30);
+ func_mysqli_fetch_all($link, $engine, "TINYINT UNSIGNED", 1, "1", 40);
+ func_mysqli_fetch_all($link, $engine, "TINYINT UNSIGNED", NULL, NULL, 50);
+
+ func_mysqli_fetch_all($link, $engine, "BOOL", 1, "1", 60);
+ func_mysqli_fetch_all($link, $engine, "BOOL", NULL, NULL, 70);
+ func_mysqli_fetch_all($link, $engine, "BOOLEAN", 0, "0", 80);
+ func_mysqli_fetch_all($link, $engine, "BOOLEAN", NULL, NULL, 90);
+
+ func_mysqli_fetch_all($link, $engine, "SMALLINT", -32768, "-32768", 100);
+ func_mysqli_fetch_all($link, $engine, "SMALLINT", 32767, "32767", 110);
+ func_mysqli_fetch_all($link, $engine, "SMALLINT", NULL, NULL, 120);
+ func_mysqli_fetch_all($link, $engine, "SMALLINT UNSIGNED", 65535, "65535", 130);
+ func_mysqli_fetch_all($link, $engine, "SMALLINT UNSIGNED", NULL, NULL, 140);
+
+ func_mysqli_fetch_all($link, $engine, "MEDIUMINT", -8388608, "-8388608", 150);
+ func_mysqli_fetch_all($link, $engine, "MEDIUMINT", 8388607, "8388607", 160);
+ func_mysqli_fetch_all($link, $engine, "MEDIUMINT", NULL, NULL, 170);
+ func_mysqli_fetch_all($link, $engine, "MEDIUMINT UNSIGNED", 16777215, "16777215", 180);
+ func_mysqli_fetch_all($link, $engine, "MEDIUMINT UNSIGNED", NULL, NULL, 190);
+
+ func_mysqli_fetch_all($link, $engine, "INTEGER", -2147483648, "-2147483648", 200);
+ func_mysqli_fetch_all($link, $engine, "INTEGER", 2147483647, "2147483647", 210);
+ func_mysqli_fetch_all($link, $engine, "INTEGER", NULL, NULL, 220);
+ func_mysqli_fetch_all($link, $engine, "INTEGER UNSIGNED", "4294967295", "4294967295", 230);
+ func_mysqli_fetch_all($link, $engine, "INTEGER UNSIGNED", NULL, NULL, 240);
+
+ func_mysqli_fetch_all($link, $engine, "BIGINT", "-9223372036854775808", "-9223372036854775808", 250);
+
+ func_mysqli_fetch_all($link, $engine, "BIGINT", NULL, NULL, 260);
+ func_mysqli_fetch_all($link, $engine, "BIGINT UNSIGNED", "18446744073709551615", "18446744073709551615", 270);
+ func_mysqli_fetch_all($link, $engine, "BIGINT UNSIGNED", NULL, NULL, 280);
+
+ func_mysqli_fetch_all($link, $engine, "FLOAT", (string)(-9223372036854775808 - 1.1), "-9.22337e+18", 290, "/-9\.22337e\+?[0]?18/iu");
+ func_mysqli_fetch_all($link, $engine, "FLOAT", NULL, NULL, 300);
+ func_mysqli_fetch_all($link, $engine, "FLOAT UNSIGNED", (string)(18446744073709551615 + 1.1), "1.84467e+19", 310, "/1\.84467e\+?[0]?19/iu");
+ func_mysqli_fetch_all($link, $engine, "FLOAT UNSIGNED ", NULL, NULL, 320);
+
+ func_mysqli_fetch_all($link, $engine, "DOUBLE(10,2)", "-99999999.99", "-99999999.99", 330);
+ func_mysqli_fetch_all($link, $engine, "DOUBLE(10,2)", NULL, NULL, 340);
+ func_mysqli_fetch_all($link, $engine, "DOUBLE(10,2) UNSIGNED", "99999999.99", "99999999.99", 350);
+ func_mysqli_fetch_all($link, $engine, "DOUBLE(10,2) UNSIGNED", NULL, NULL, 360);
+
+ func_mysqli_fetch_all($link, $engine, "DECIMAL(10,2)", "-99999999.99", "-99999999.99", 370);
+ func_mysqli_fetch_all($link, $engine, "DECIMAL(10,2)", NULL, NULL, 380);
+ func_mysqli_fetch_all($link, $engine, "DECIMAL(10,2)", "99999999.99", "99999999.99", 390);
+ func_mysqli_fetch_all($link, $engine, "DECIMAL(10,2)", NULL, NULL, 400);
+
+ // don't care about date() strict TZ warnings...
+ func_mysqli_fetch_all($link, $engine, "DATE", @date('Y-m-d'), @date('Y-m-d'), 410);
+ func_mysqli_fetch_all($link, $engine, "DATE NOT NULL", @date('Y-m-d'), @date('Y-m-d'), 420);
+ func_mysqli_fetch_all($link, $engine, "DATE", NULL, NULL, 430);
+
+ func_mysqli_fetch_all($link, $engine, "DATETIME", @date('Y-m-d H:i:s'), @date('Y-m-d H:i:s'), 440);
+ func_mysqli_fetch_all($link, $engine, "DATETIME NOT NULL", @date('Y-m-d H:i:s'), @date('Y-m-d H:i:s'), 450);
+ func_mysqli_fetch_all($link, $engine, "DATETIME", NULL, NULL, 460);
+
+ func_mysqli_fetch_all($link, $engine, "TIMESTAMP", @date('Y-m-d H:i:s'), @date('Y-m-d H:i:s'), 470);
+
+ func_mysqli_fetch_all($link, $engine, "TIME", @date('H:i:s'), @date('H:i:s'), 480);
+ func_mysqli_fetch_all($link, $engine, "TIME NOT NULL", @date('H:i:s'), @date('H:i:s'), 490);
+ func_mysqli_fetch_all($link, $engine, "TIME", NULL, NULL, 500);
+
+ func_mysqli_fetch_all($link, $engine, "YEAR", @date('Y'), @date('Y'), 510);
+ func_mysqli_fetch_all($link, $engine, "YEAR NOT NULL", @date('Y'), @date('Y'), 520);
+ func_mysqli_fetch_all($link, $engine, "YEAR", NULL, NULL, 530);
+
+ $string255 = func_mysqli_fetch_array_make_string(255);
+ func_mysqli_fetch_all($link, $engine, "CHAR(1)", "a", "a", 540);
+ func_mysqli_fetch_all($link, $engine, "CHAR(255)", $string255, $string255, 550);
+ func_mysqli_fetch_all($link, $engine, "CHAR(1) NOT NULL", "a", "a", 560);
+ func_mysqli_fetch_all($link, $engine, "CHAR(1)", NULL, NULL, 570);
+
+ $string65k = func_mysqli_fetch_array_make_string(65400);
+ func_mysqli_fetch_all($link, $engine, "VARCHAR(1)", "a", "a", 580);
+ func_mysqli_fetch_all($link, $engine, "VARCHAR(255)", $string255, $string255, 590);
+ func_mysqli_fetch_all($link, $engine, "VARCHAR(65400)", $string65k, $string65k, 600);
+ func_mysqli_fetch_all($link, $engine, "VARCHAR(1) NOT NULL", "a", "a", 610);
+ func_mysqli_fetch_all($link, $engine, "VARCHAR(1)", NULL, NULL, 620);
+
+ func_mysqli_fetch_all($link, $engine, "BINARY(1)", "a", "a", 630);
+ func_mysqli_fetch_all($link, $engine, "BINARY(2)", chr(0) . "a", chr(0) . "a", 640);
+ func_mysqli_fetch_all($link, $engine, "BINARY(1) NOT NULL", "b", "b", 650);
+ func_mysqli_fetch_all($link, $engine, "BINARY(1)", NULL, NULL, 660);
+
+ func_mysqli_fetch_all($link, $engine, "VARBINARY(1)", "a", "a", 670);
+ func_mysqli_fetch_all($link, $engine, "VARBINARY(2)", chr(0) . "a", chr(0) . "a", 680);
+ func_mysqli_fetch_all($link, $engine, "VARBINARY(1) NOT NULL", "b", "b", 690);
+ func_mysqli_fetch_all($link, $engine, "VARBINARY(1)", NULL, NULL, 700);
+
+ func_mysqli_fetch_all($link, $engine, "TINYBLOB", "a", "a", 710);
+ func_mysqli_fetch_all($link, $engine, "TINYBLOB", chr(0) . "a", chr(0) . "a", 720);
+ func_mysqli_fetch_all($link, $engine, "TINYBLOB NOT NULL", "b", "b", 730);
+ func_mysqli_fetch_all($link, $engine, "TINYBLOB", NULL, NULL, 740);
+
+ func_mysqli_fetch_all($link, $engine, "TINYTEXT", "a", "a", 750);
+ func_mysqli_fetch_all($link, $engine, "TINYTEXT NOT NULL", "a", "a", 760);
+ func_mysqli_fetch_all($link, $engine, "TINYTEXT", NULL, NULL, 770);
+
+ func_mysqli_fetch_all($link, $engine, "BLOB", "a", "a", 780);
+ func_mysqli_fetch_all($link, $engine, "BLOB", chr(0) . "a", chr(0) . "a", 780);
+ func_mysqli_fetch_all($link, $engine, "BLOB", NULL, NULL, 790);
+
+ func_mysqli_fetch_all($link, $engine, "TEXT", "a", "a", 800);
+ func_mysqli_fetch_all($link, $engine, "TEXT", chr(0) . "a", chr(0) . "a", 810);
+ func_mysqli_fetch_all($link, $engine, "TEXT", NULL, NULL, 820);
+
+ func_mysqli_fetch_all($link, $engine, "MEDIUMBLOB", "a", "a", 830);
+ func_mysqli_fetch_all($link, $engine, "MEDIUMBLOB", chr(0) . "a", chr(0) . "a", 840);
+ func_mysqli_fetch_all($link, $engine, "MEDIUMBLOB", NULL, NULL, 850);
+
+ func_mysqli_fetch_all($link, $engine, "MEDIUMTEXT", "a", "a", 860);
+ func_mysqli_fetch_all($link, $engine, "MEDIUMTEXT", chr(0) . "a", chr(0) . "a", 870);
+ func_mysqli_fetch_all($link, $engine, "MEDIUMTEXT", NULL, NULL, 880);
+
+ func_mysqli_fetch_all($link, $engine, "LONGBLOB", "a", "a", 890);
+ func_mysqli_fetch_all($link, $engine, "LONGTEXT", chr(0) . "a", chr(0) . "a", 900);
+ func_mysqli_fetch_all($link, $engine, "LONGBLOB", NULL, NULL, 910);
+
+ func_mysqli_fetch_all($link, $engine, "ENUM('a', 'b')", "a", "a", 920);
+ func_mysqli_fetch_all($link, $engine, "ENUM('a', 'b')", NULL, NULL, 930);
+
+ func_mysqli_fetch_all($link, $engine, "SET('a', 'b')", "a", "a", 940);
+ func_mysqli_fetch_all($link, $engine, "SET('a', 'b')", NULL, NULL, 950);
+
+ mysqli_close($link);
+
+ if (null !== ($tmp = mysqli_fetch_array($res, MYSQLI_ASSOC)))
+ printf("[015] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ // require_once("clean_table.inc");
+?>
+--EXPECTF--
+[005]
+array(2) {
+ [0]=>
+ array(2) {
+ [0]=>
+ %unicode|string%(1) "1"
+ [1]=>
+ %unicode|string%(1) "a"
+ }
+ [1]=>
+ array(2) {
+ [0]=>
+ %unicode|string%(1) "2"
+ [1]=>
+ %unicode|string%(1) "b"
+ }
+}
+[007]
+array(2) {
+ [0]=>
+ array(2) {
+ [0]=>
+ %unicode|string%(1) "1"
+ [1]=>
+ %unicode|string%(1) "a"
+ }
+ [1]=>
+ array(2) {
+ [0]=>
+ %unicode|string%(1) "2"
+ [1]=>
+ %unicode|string%(1) "b"
+ }
+}
+[008]
+array(2) {
+ [0]=>
+ array(4) {
+ [0]=>
+ %unicode|string%(1) "1"
+ [%u|b%"id"]=>
+ %unicode|string%(1) "1"
+ [1]=>
+ %unicode|string%(1) "a"
+ [%u|b%"label"]=>
+ %unicode|string%(1) "a"
+ }
+ [1]=>
+ array(4) {
+ [0]=>
+ %unicode|string%(1) "2"
+ [%u|b%"id"]=>
+ %unicode|string%(1) "2"
+ [1]=>
+ %unicode|string%(1) "b"
+ [%u|b%"label"]=>
+ %unicode|string%(1) "b"
+ }
+}
+[010]
+array(2) {
+ [0]=>
+ array(2) {
+ [%u|b%"id"]=>
+ %unicode|string%(1) "1"
+ [%u|b%"label"]=>
+ %unicode|string%(1) "a"
+ }
+ [1]=>
+ array(2) {
+ [%u|b%"id"]=>
+ %unicode|string%(1) "2"
+ [%u|b%"label"]=>
+ %unicode|string%(1) "b"
+ }
+}
+[011]
+array(0) {
+}
+[013]
+array(2) {
+ [0]=>
+ array(2) {
+ [%u|b%"id"]=>
+ %unicode|string%(1) "1"
+ [%u|b%"label"]=>
+ %unicode|string%(1) "a"
+ }
+ [1]=>
+ array(2) {
+ [%u|b%"id"]=>
+ %unicode|string%(1) "2"
+ [%u|b%"label"]=>
+ %unicode|string%(1) "b"
+ }
+}
+[016]
+array(0) {
+}
+[017]
+array(1) {
+ [0]=>
+ array(11) {
+ [0]=>
+ %unicode|string%(1) "1"
+ [%u|b%"a"]=>
+ %unicode|string%(1) "2"
+ [1]=>
+ %unicode|string%(1) "2"
+ [2]=>
+ %unicode|string%(1) "3"
+ [%u|b%"c"]=>
+ %unicode|string%(1) "3"
+ [3]=>
+ %unicode|string%(1) "4"
+ [%u|b%"C"]=>
+ %unicode|string%(1) "4"
+ [4]=>
+ NULL
+ [%u|b%"d"]=>
+ NULL
+ [5]=>
+ %unicode|string%(1) "1"
+ [%u|b%"e"]=>
+ %unicode|string%(1) "1"
+ }
+}
+
+Warning: mysqli_fetch_all(): Mode can be only MYSQLI_FETCH_NUM, MYSQLI_FETCH_ASSOC or MYSQLI_FETCH_BOTH in %s on line %d
+
+Warning: mysqli_fetch_array(): Couldn't fetch mysqli_result in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_fetch_all_oo.phpt b/ext/mysqli/tests/mysqli_fetch_all_oo.phpt
new file mode 100644
index 0000000..575f953
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_fetch_all_oo.phpt
@@ -0,0 +1,440 @@
+--TEST--
+$mysqli->fetch_all() (introduced with mysqlnd)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+if (!function_exists('mysqli_fetch_all'))
+ die("skip: function only available with mysqlnd");
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ $mysqli = new mysqli();
+
+ if (!$mysqli = new my_mysqli($host, $user, $passwd, $db, $port, $socket))
+ printf("[002] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ require('table.inc');
+ if (!$res = $mysqli->query("SELECT * FROM test ORDER BY id LIMIT 2")) {
+ printf("[004] [%d] %s\n", $mysqli->errno, $mysqli->error);
+ }
+
+ print "[005]\n";
+ var_dump($res->fetch_all());
+ $res->free_result();
+
+ if (!$res = $mysqli->query("SELECT * FROM test ORDER BY id LIMIT 2")) {
+ printf("[006] [%d] %s\n", $mysqli->errno, $mysqli->error);
+ }
+
+ print "[007]\n";
+ var_dump($res->fetch_all(MYSQLI_NUM));
+ $res->free_result();
+
+ if (!$res = $mysqli->query("SELECT * FROM test ORDER BY id LIMIT 2")) {
+ printf("[008] [%d] %s\n", $mysqli->errno, $mysqli->error);
+ }
+
+ print "[008]\n";
+ var_dump($res->fetch_all(MYSQLI_BOTH));
+ $res->free_result();
+
+ if (!$res = $mysqli->query("SELECT * FROM test ORDER BY id LIMIT 2")) {
+ printf("[009] [%d] %s\n", $mysqli->errno, $mysqli->error);
+ }
+
+ print "[010]\n";
+ var_dump($res->fetch_all(MYSQLI_ASSOC));
+
+ print "[011]\n";
+ var_dump($res->fetch_array());
+ $res->free_result();
+
+ if (!$res = $mysqli->query("SELECT * FROM test ORDER BY id LIMIT 2")) {
+ printf("[012] [%d] %s\n", $mysqli->errno, $mysqli->error);
+ }
+
+ print "[013]\n";
+ var_dump($res->fetch_all(MYSQLI_ASSOC));
+
+ print "[016]\n";
+ var_dump($res->fetch_array());
+
+ if (!$res = $mysqli->query("SELECT 1 AS a, 2 AS a, 3 AS c, 4 AS C, NULL AS d, true AS e")) {
+ printf("[010] Cannot run query, [%d] %s\n", $mysqli->errno, $$mysqli->error);
+ }
+ print "[017]\n";
+ var_dump($res->fetch_all(MYSQLI_BOTH));
+
+ $res->free_result();
+ if (!$res = $mysqli->query("SELECT 1 AS a, 2 AS b, 3 AS c, 4 AS C")) {
+ printf("[018] Cannot run query, [%d] %s\n",
+ $mysqli->errno, $$mysqli->error);
+ exit(1);
+ }
+
+ do {
+ $illegal_mode = mt_rand(-10000, 10000);
+ } while (in_array($illegal_mode, array(MYSQLI_ASSOC, MYSQLI_NUM, MYSQLI_BOTH)));
+ // NOTE: for BC reasons with ext/mysql, ext/mysqli accepts invalid result modes.
+ $tmp = $res->fetch_all($illegal_mode);
+ if (false !== $tmp)
+ printf("[019] Expecting boolean/false although, got %s/%s. [%d] %s\n",
+ gettype($tmp), $tmp, $mysqli->errno, $mysqli->error);
+
+ $res->free_result();
+
+ function func_mysqli_fetch_all_oo($link, $engine, $sql_type, $sql_value, $php_value, $offset, $regexp_comparison = NULL) {
+
+ if (!$link->query("DROP TABLE IF EXISTS test")) {
+ printf("[%04d] [%d] %s\n", $offset, $link->errno, $link->error);
+ return false;
+ }
+
+ if (!$link->query($sql = sprintf("CREATE TABLE test(id INT NOT NULL, label %s, PRIMARY KEY(id)) ENGINE = %s", $sql_type, $engine))) {
+ // don't bail, engine might not support the datatype
+ return false;
+ }
+
+ if (is_null($php_value)) {
+ if (!$link->query($sql = sprintf("INSERT INTO test(id, label) VALUES (1, NULL)"))) {
+ printf("[%04d] [%d] %s\n", $offset + 1, $link->errno, $link->error);
+ return false;
+ }
+ } else {
+ if (is_string($sql_value)) {
+ if (!$link->query($sql = "INSERT INTO test(id, label) VALUES (1, '" . $sql_value . "')")) {
+ printf("[%04ds] [%d] %s - %s\n", $offset + 1, $link->errno, $link->error, $sql);
+ return false;
+ }
+ } else {
+ if (!$link->query($sql = sprintf("INSERT INTO test(id, label) VALUES (1, '%d')", $sql_value))) {
+ printf("[%04di] [%d] %s\n", $offset + 1, $link->errno, $link->error);
+ return false;
+ }
+ }
+ }
+
+ if (!$res = $link->query("SELECT id, label FROM test")) {
+ printf("[%04d] [%d] %s\n", $offset + 2, $link->errno, $link->error);
+ return false;
+ }
+
+ if (!$tmp = $res->fetch_all(MYSQLI_BOTH)) {
+ printf("[%04d] [%d] %s\n", $offset + 3, $link->errno, $link->error);
+ return false;
+ }
+ $row = $tmp[0];
+
+ $fields = mysqli_fetch_fields($res);
+
+ if (!(gettype($php_value)=="unicode" && ($fields[1]->flags & 128))) {
+ if ($regexp_comparison) {
+ if (!preg_match($regexp_comparison, (string)$row['label']) || !preg_match($regexp_comparison, (string)$row[1])) {
+ printf("[%04d] Expecting %s/%s [reg exp = %s], got %s/%s resp. %s/%s. [%d] %s\n", $offset + 4,
+ gettype($php_value), $php_value, $regexp_comparison,
+ gettype($row[1]), $row[1],
+ gettype($row['label']), $row['label'], $link->errno, $link->error);
+ return false;
+ }
+ } else {
+ if (($row['label'] !== $php_value) || ($row[1] != $php_value)) {
+ printf("[%04d] Expecting %s/%s, got %s/%s resp. %s/%s. [%d] %s\n", $offset + 4,
+ gettype($php_value), $php_value,
+ gettype($row[1]), $row[1],
+ gettype($row['label']), $row['label'], $link->errno, $link->error);
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ function func_mysqli_fetch_array_oo_make_string($len) {
+
+ $ret = '';
+ for ($i = 0; $i < $len; $i++)
+ $ret .= chr(mt_rand(65, 90));
+
+ return $ret;
+ }
+
+ func_mysqli_fetch_all_oo($link, $engine, "TINYINT", -11, "-11", 20);
+ func_mysqli_fetch_all_oo($link, $engine, "TINYINT", NULL, NULL, 30);
+ func_mysqli_fetch_all_oo($link, $engine, "TINYINT UNSIGNED", 1, "1", 40);
+ func_mysqli_fetch_all_oo($link, $engine, "TINYINT UNSIGNED", NULL, NULL, 50);
+
+ func_mysqli_fetch_all_oo($link, $engine, "BOOL", 1, "1", 60);
+ func_mysqli_fetch_all_oo($link, $engine, "BOOL", NULL, NULL, 70);
+ func_mysqli_fetch_all_oo($link, $engine, "BOOLEAN", 0, "0", 80);
+ func_mysqli_fetch_all_oo($link, $engine, "BOOLEAN", NULL, NULL, 90);
+
+ func_mysqli_fetch_all_oo($link, $engine, "SMALLINT", -32768, "-32768", 100);
+ func_mysqli_fetch_all_oo($link, $engine, "SMALLINT", 32767, "32767", 110);
+ func_mysqli_fetch_all_oo($link, $engine, "SMALLINT", NULL, NULL, 120);
+ func_mysqli_fetch_all_oo($link, $engine, "SMALLINT UNSIGNED", 65400, "65400", 130);
+ func_mysqli_fetch_all_oo($link, $engine, "SMALLINT UNSIGNED", NULL, NULL, 140);
+
+ func_mysqli_fetch_all_oo($link, $engine, "MEDIUMINT", -8388608, "-8388608", 150);
+ func_mysqli_fetch_all_oo($link, $engine, "MEDIUMINT", 8388607, "8388607", 160);
+ func_mysqli_fetch_all_oo($link, $engine, "MEDIUMINT", NULL, NULL, 170);
+ func_mysqli_fetch_all_oo($link, $engine, "MEDIUMINT UNSIGNED", 16777215, "16777215", 180);
+ func_mysqli_fetch_all_oo($link, $engine, "MEDIUMINT UNSIGNED", NULL, NULL, 190);
+
+ func_mysqli_fetch_all_oo($link, $engine, "INTEGER", -2147483648, "-2147483648", 200);
+ func_mysqli_fetch_all_oo($link, $engine, "INTEGER", 2147483647, "2147483647", 210);
+ func_mysqli_fetch_all_oo($link, $engine, "INTEGER", NULL, NULL, 220);
+ func_mysqli_fetch_all_oo($link, $engine, "INTEGER UNSIGNED", "4294967295", "4294967295", 230);
+ func_mysqli_fetch_all_oo($link, $engine, "INTEGER UNSIGNED", NULL, NULL, 240);
+
+ func_mysqli_fetch_all_oo($link, $engine, "BIGINT", "-9223372036854775808", "-9223372036854775808", 250);
+ func_mysqli_fetch_all_oo($link, $engine, "BIGINT", NULL, NULL, 260);
+ func_mysqli_fetch_all_oo($link, $engine, "BIGINT UNSIGNED", "18446744073709551615", "18446744073709551615", 270);
+ func_mysqli_fetch_all_oo($link, $engine, "BIGINT UNSIGNED", NULL, NULL, 280);
+
+ func_mysqli_fetch_all_oo($link, $engine, "FLOAT", (string)(-9223372036854775808 - 1.1), "-9.22337e+18", 290, "/-9\.22337e\+?[0]?18/iu");
+ func_mysqli_fetch_all_oo($link, $engine, "FLOAT", NULL, NULL, 300);
+ func_mysqli_fetch_all_oo($link, $engine, "FLOAT UNSIGNED", (string)(18446744073709551615 + 1.1), "1.84467e+?19", 310, "/1\.84467e\+?[0]?19/iu");
+ func_mysqli_fetch_all_oo($link, $engine, "FLOAT UNSIGNED ", NULL, NULL, 320);
+
+ func_mysqli_fetch_all_oo($link, $engine, "DOUBLE(10,2)", "-99999999.99", "-99999999.99", 330);
+ func_mysqli_fetch_all_oo($link, $engine, "DOUBLE(10,2)", NULL, NULL, 340);
+ func_mysqli_fetch_all_oo($link, $engine, "DOUBLE(10,2) UNSIGNED", "99999999.99", "99999999.99", 350);
+ func_mysqli_fetch_all_oo($link, $engine, "DOUBLE(10,2) UNSIGNED", NULL, NULL, 360);
+
+ func_mysqli_fetch_all_oo($link, $engine, "DECIMAL(10,2)", "-99999999.99", "-99999999.99", 370);
+ func_mysqli_fetch_all_oo($link, $engine, "DECIMAL(10,2)", NULL, NULL, 380);
+ func_mysqli_fetch_all_oo($link, $engine, "DECIMAL(10,2)", "99999999.99", "99999999.99", 390);
+ func_mysqli_fetch_all_oo($link, $engine, "DECIMAL(10,2)", NULL, NULL, 400);
+
+ // don't care about date() strict TZ warnings...
+ $date = @date('Y-m-d');
+ func_mysqli_fetch_all_oo($link, $engine, "DATE", $date, $date, 410);
+ func_mysqli_fetch_all_oo($link, $engine, "DATE NOT NULL", $date, $date, 420);
+ func_mysqli_fetch_all_oo($link, $engine, "DATE", NULL, NULL, 430);
+
+ $datetime = @date('Y-m-d H:i:s');
+ func_mysqli_fetch_all_oo($link, $engine, "DATETIME", $datetime, $datetime, 440);
+ func_mysqli_fetch_all_oo($link, $engine, "DATETIME NOT NULL", $datetime, $datetime, 450);
+ func_mysqli_fetch_all_oo($link, $engine, "DATETIME", NULL, NULL, 460);
+
+ func_mysqli_fetch_all_oo($link, $engine, "TIMESTAMP", $datetime, $datetime, 470);
+
+ $time = @date('H:i:s');
+ func_mysqli_fetch_all_oo($link, $engine, "TIME", $time, $time, 480);
+ func_mysqli_fetch_all_oo($link, $engine, "TIME NOT NULL", $time, $time, 490);
+ func_mysqli_fetch_all_oo($link, $engine, "TIME", NULL, NULL, 500);
+
+ func_mysqli_fetch_all_oo($link, $engine, "YEAR", @date('Y'), @date('Y'), 510);
+ func_mysqli_fetch_all_oo($link, $engine, "YEAR NOT NULL", @date('Y'), @date('Y'), 520);
+ func_mysqli_fetch_all_oo($link, $engine, "YEAR", NULL, NULL, 530);
+
+ $string255 = func_mysqli_fetch_array_oo_make_string(255);
+ func_mysqli_fetch_all_oo($link, $engine, "CHAR(1)", "a", "a", 540);
+ func_mysqli_fetch_all_oo($link, $engine, "CHAR(255)", $string255, $string255, 550);
+ func_mysqli_fetch_all_oo($link, $engine, "CHAR(1) NOT NULL", "a", "a", 560);
+ func_mysqli_fetch_all_oo($link, $engine, "CHAR(1)", NULL, NULL, 570);
+
+ $string65k = func_mysqli_fetch_array_oo_make_string(65400);
+ func_mysqli_fetch_all_oo($link, $engine, "VARCHAR(1)", "a", "a", 580);
+ func_mysqli_fetch_all_oo($link, $engine, "VARCHAR(255)", $string255, $string255, 590);
+ func_mysqli_fetch_all_oo($link, $engine, "VARCHAR(65400)", $string65k, $string65k, 600);
+ func_mysqli_fetch_all_oo($link, $engine, "VARCHAR(1) NOT NULL", "a", "a", 610);
+ func_mysqli_fetch_all_oo($link, $engine, "VARCHAR(1)", NULL, NULL, 620);
+
+ func_mysqli_fetch_all_oo($link, $engine, "BINARY(1)", "a", "a", 630);
+ func_mysqli_fetch_all_oo($link, $engine, "BINARY(2)", chr(0) . "a", chr(0) . "a", 640);
+ func_mysqli_fetch_all_oo($link, $engine, "BINARY(1) NOT NULL", "b", "b", 650);
+ func_mysqli_fetch_all_oo($link, $engine, "BINARY(1)", NULL, NULL, 660);
+
+ func_mysqli_fetch_all_oo($link, $engine, "VARBINARY(1)", "a", "a", 670);
+ func_mysqli_fetch_all_oo($link, $engine, "VARBINARY(2)", chr(0) . "a", chr(0) . "a", 680);
+ func_mysqli_fetch_all_oo($link, $engine, "VARBINARY(1) NOT NULL", "b", "b", 690);
+ func_mysqli_fetch_all_oo($link, $engine, "VARBINARY(1)", NULL, NULL, 700);
+
+ func_mysqli_fetch_all_oo($link, $engine, "TINYBLOB", "a", "a", 710);
+ func_mysqli_fetch_all_oo($link, $engine, "TINYBLOB", chr(0) . "a", chr(0) . "a", 720);
+ func_mysqli_fetch_all_oo($link, $engine, "TINYBLOB NOT NULL", "b", "b", 730);
+ func_mysqli_fetch_all_oo($link, $engine, "TINYBLOB", NULL, NULL, 740);
+
+ func_mysqli_fetch_all_oo($link, $engine, "TINYTEXT", "a", "a", 750);
+ func_mysqli_fetch_all_oo($link, $engine, "TINYTEXT NOT NULL", "a", "a", 760);
+ func_mysqli_fetch_all_oo($link, $engine, "TINYTEXT", NULL, NULL, 770);
+
+ func_mysqli_fetch_all_oo($link, $engine, "BLOB", "a", "a", 780);
+ func_mysqli_fetch_all_oo($link, $engine, "BLOB", chr(0) . "a", chr(0) . "a", 780);
+ func_mysqli_fetch_all_oo($link, $engine, "BLOB", NULL, NULL, 790);
+
+ func_mysqli_fetch_all_oo($link, $engine, "TEXT", "a", "a", 800);
+ func_mysqli_fetch_all_oo($link, $engine, "TEXT", chr(0) . "a", chr(0) . "a", 810);
+ func_mysqli_fetch_all_oo($link, $engine, "TEXT", NULL, NULL, 820);
+
+ func_mysqli_fetch_all_oo($link, $engine, "MEDIUMBLOB", "a", "a", 830);
+ func_mysqli_fetch_all_oo($link, $engine, "MEDIUMBLOB", chr(0) . "a", chr(0) . "a", 840);
+ func_mysqli_fetch_all_oo($link, $engine, "MEDIUMBLOB", NULL, NULL, 850);
+
+ func_mysqli_fetch_all_oo($link, $engine, "MEDIUMTEXT", "a", "a", 860);
+ func_mysqli_fetch_all_oo($link, $engine, "MEDIUMTEXT", chr(0) . "a", chr(0) . "a", 870);
+ func_mysqli_fetch_all_oo($link, $engine, "MEDIUMTEXT", NULL, NULL, 880);
+
+ func_mysqli_fetch_all_oo($link, $engine, "LONGBLOB", "a", "a", 890);
+ func_mysqli_fetch_all_oo($link, $engine, "LONGTEXT", chr(0) . "a", chr(0) . "a", 900);
+ func_mysqli_fetch_all_oo($link, $engine, "LONGBLOB", NULL, NULL, 910);
+
+ func_mysqli_fetch_all_oo($link, $engine, "ENUM('a', 'b')", "a", "a", 920);
+ func_mysqli_fetch_all_oo($link, $engine, "ENUM('a', 'b')", NULL, NULL, 930);
+
+ func_mysqli_fetch_all_oo($link, $engine, "SET('a', 'b')", "a", "a", 940);
+ func_mysqli_fetch_all_oo($link, $engine, "SET('a', 'b')", NULL, NULL, 950);
+
+ mysqli_close($link);
+
+ if (null !== ($tmp = $res->fetch_array(MYSQLI_ASSOC)))
+ printf("[015] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+[005]
+array(2) {
+ [0]=>
+ array(2) {
+ [0]=>
+ %unicode|string%(1) "1"
+ [1]=>
+ %unicode|string%(1) "a"
+ }
+ [1]=>
+ array(2) {
+ [0]=>
+ %unicode|string%(1) "2"
+ [1]=>
+ %unicode|string%(1) "b"
+ }
+}
+[007]
+array(2) {
+ [0]=>
+ array(2) {
+ [0]=>
+ %unicode|string%(1) "1"
+ [1]=>
+ %unicode|string%(1) "a"
+ }
+ [1]=>
+ array(2) {
+ [0]=>
+ %unicode|string%(1) "2"
+ [1]=>
+ %unicode|string%(1) "b"
+ }
+}
+[008]
+array(2) {
+ [0]=>
+ array(4) {
+ [0]=>
+ %unicode|string%(1) "1"
+ [%u|b%"id"]=>
+ %unicode|string%(1) "1"
+ [1]=>
+ %unicode|string%(1) "a"
+ [%u|b%"label"]=>
+ %unicode|string%(1) "a"
+ }
+ [1]=>
+ array(4) {
+ [0]=>
+ %unicode|string%(1) "2"
+ [%u|b%"id"]=>
+ %unicode|string%(1) "2"
+ [1]=>
+ %unicode|string%(1) "b"
+ [%u|b%"label"]=>
+ %unicode|string%(1) "b"
+ }
+}
+[010]
+array(2) {
+ [0]=>
+ array(2) {
+ [%u|b%"id"]=>
+ %unicode|string%(1) "1"
+ [%u|b%"label"]=>
+ %unicode|string%(1) "a"
+ }
+ [1]=>
+ array(2) {
+ [%u|b%"id"]=>
+ %unicode|string%(1) "2"
+ [%u|b%"label"]=>
+ %unicode|string%(1) "b"
+ }
+}
+[011]
+NULL
+[013]
+array(2) {
+ [0]=>
+ array(2) {
+ [%u|b%"id"]=>
+ %unicode|string%(1) "1"
+ [%u|b%"label"]=>
+ %unicode|string%(1) "a"
+ }
+ [1]=>
+ array(2) {
+ [%u|b%"id"]=>
+ %unicode|string%(1) "2"
+ [%u|b%"label"]=>
+ %unicode|string%(1) "b"
+ }
+}
+[016]
+NULL
+[017]
+array(1) {
+ [0]=>
+ array(11) {
+ [0]=>
+ %unicode|string%(1) "1"
+ [%u|b%"a"]=>
+ %unicode|string%(1) "2"
+ [1]=>
+ %unicode|string%(1) "2"
+ [2]=>
+ %unicode|string%(1) "3"
+ [%u|b%"c"]=>
+ %unicode|string%(1) "3"
+ [3]=>
+ %unicode|string%(1) "4"
+ [%u|b%"C"]=>
+ %unicode|string%(1) "4"
+ [4]=>
+ NULL
+ [%u|b%"d"]=>
+ NULL
+ [5]=>
+ %unicode|string%(1) "1"
+ [%u|b%"e"]=>
+ %unicode|string%(1) "1"
+ }
+}
+
+Warning: mysqli_result::fetch_all(): Mode can be only MYSQLI_FETCH_NUM, MYSQLI_FETCH_ASSOC or MYSQLI_FETCH_BOTH in %s on line %d
+
+Warning: mysqli_result::fetch_array(): Couldn't fetch mysqli_result in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_fetch_array.phpt b/ext/mysqli/tests/mysqli_fetch_array.phpt
new file mode 100644
index 0000000..aa19ff6
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_fetch_array.phpt
@@ -0,0 +1,374 @@
+--TEST--
+mysqli_fetch_array() - all datatypes but BIT
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_fetch_array()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_fetch_array($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+ if (!$res = mysqli_query($link, "SELECT * FROM test ORDER BY id LIMIT 5")) {
+ printf("[004] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ print "[005]\n";
+ var_dump(mysqli_fetch_array($res));
+
+ print "[006]\n";
+ var_dump(mysqli_fetch_array($res, MYSQLI_NUM));
+
+ print "[007]\n";
+ var_dump(mysqli_fetch_array($res, MYSQLI_BOTH));
+
+ print "[008]\n";
+ var_dump(mysqli_fetch_array($res, MYSQLI_ASSOC));
+
+ print "[009]\n";
+ var_dump(mysqli_fetch_array($res));
+
+ mysqli_free_result($res);
+
+ if (!$res = mysqli_query($link, "SELECT 1 AS a, 2 AS a, 3 AS c, 4 AS C, NULL AS d, true AS e")) {
+ printf("[010] Cannot run query, [%d] %s\n", mysqli_errno($link), $mysqli_error($link));
+ }
+ print "[011]\n";
+ var_dump(mysqli_fetch_array($res, MYSQLI_BOTH));
+
+ mysqli_free_result($res);
+ if (!$res = mysqli_query($link, "SELECT 1 AS a, 2 AS b, 3 AS c, 4 AS C")) {
+ printf("[012] Cannot run query, [%d] %s\n",
+ mysqli_errno($link), $mysqli_error($link));
+ exit(1);
+ }
+
+ do {
+ $illegal_mode = mt_rand(-10000, 10000);
+ } while (in_array($illegal_mode, array(MYSQLI_ASSOC, MYSQLI_NUM, MYSQLI_BOTH)));
+ // NOTE: for BC reasons with ext/mysql, ext/mysqli accepts invalid result modes.
+ $tmp = mysqli_fetch_array($res, $illegal_mode);
+ if (false !== $tmp)
+ printf("[013] Expecting boolean/false although, got %s/%s. [%d] %s\n",
+ gettype($tmp), $tmp, mysqli_errno($link), mysqli_error($link));
+
+ $tmp = mysqli_fetch_array($res, $illegal_mode);
+ if (false !== $tmp)
+ printf("[014] Expecting boolean/false, got %s/%s. [%d] %s\n",
+ gettype($tmp), $tmp, mysqli_errno($link), mysqli_error($link));
+
+ mysqli_free_result($res);
+
+ function func_mysqli_fetch_array($link, $engine, $sql_type, $sql_value, $php_value, $offset, $regexp_comparison = NULL, $binary_type = false) {
+
+ if (!mysqli_query($link, "DROP TABLE IF EXISTS test")) {
+ printf("[%04d] [%d] %s\n", $offset, mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ if (!mysqli_query($link, $sql = sprintf("CREATE TABLE test(id INT NOT NULL, label %s, PRIMARY KEY(id)) ENGINE = %s", $sql_type, $engine))) {
+ // don't bail, engine might not support the datatype
+ return false;
+ }
+
+ if (is_null($php_value)) {
+ if (!mysqli_query($link, $sql = sprintf("INSERT INTO test(id, label) VALUES (1, NULL)"))) {
+ printf("[%04d] [%d] %s\n", $offset + 1, mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+ } else {
+ if (is_string($sql_value)) {
+ if (!mysqli_query($link, $sql = "INSERT INTO test(id, label) VALUES (1, '" . $sql_value . "')")) {
+ printf("[%04ds] [%d] %s - %s\n", $offset + 1, mysqli_errno($link), mysqli_error($link), $sql);
+ return false;
+ }
+ } else {
+ if (!mysqli_query($link, $sql = sprintf("INSERT INTO test(id, label) VALUES (1, '%d')", $sql_value))) {
+ printf("[%04di] [%d] %s\n", $offset + 1, mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+ }
+ }
+ if (!$res = mysqli_query($link, "SELECT id, label FROM test")) {
+ printf("[%04d] [%d] %s\n", $offset + 2, mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ if (!$row = mysqli_fetch_array($res, MYSQLI_BOTH)) {
+ printf("[%04d] [%d] %s\n", $offset + 3, mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ if ($regexp_comparison) {
+ if (!preg_match($regexp_comparison, (string)$row['label']) || !preg_match($regexp_comparison, (string)$row[1])) {
+ printf("[%04d] Expecting %s/%s [reg exp = %s], got %s/%s resp. %s/%s. [%d] %s\n", $offset + 4,
+ gettype($php_value), $php_value, $regexp_comparison,
+ gettype($row[1]), $row[1],
+ gettype($row['label']), $row['label'], mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+ } else if ((gettype($php_value) == 'unicode') && $binary_type) {
+ // Unicode is on and we are told that the MySQL column type is a binary type.
+ // Don't expect a unicode value from the database, you'll get binary string
+ if (($row['label'] != $php_value) || ($row[1] != $php_value)) {
+ printf("[%04d] Expecting %s/%s, got %s/%s resp. %s/%s. [%d] %s\n", $offset + 5,
+ gettype($php_value), $php_value,
+ gettype($row[1]), $row[1],
+ gettype($row['label']), $row['label'], mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+ if (gettype($row['label']) == 'unicode') {
+ var_dump(mysqli_fetch_field_direct($res, 1), $row['label']);
+ printf("[%04d] SQL Type: '%s', binary columns are supposed to return binary string and not unicode\n",
+ $offset + 6, $sql_type);
+ return false;
+ }
+ } else {
+ if (($row['label'] !== $php_value) || ($row[1] != $php_value)) {
+ printf("[%04d] Expecting %s/%s, got %s/%s resp. %s/%s. [%d] %s\n", $offset + 7,
+ gettype($php_value), $php_value,
+ gettype($row[1]), $row[1],
+ gettype($row['label']), $row['label'], mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+ }
+ return true;
+ }
+
+ function func_mysqli_fetch_array_make_string($len) {
+
+ $ret = '';
+ for ($i = 0; $i < $len; $i++)
+ $ret .= chr(mt_rand(65, 90));
+
+ return $ret;
+ }
+
+ func_mysqli_fetch_array($link, $engine, "TINYINT", -11, "-11", 20);
+ func_mysqli_fetch_array($link, $engine, "TINYINT", NULL, NULL, 30);
+ func_mysqli_fetch_array($link, $engine, "TINYINT UNSIGNED", 1, "1", 40);
+ func_mysqli_fetch_array($link, $engine, "TINYINT UNSIGNED", NULL, NULL, 50);
+
+ func_mysqli_fetch_array($link, $engine, "BOOL", 1, "1", 60);
+ func_mysqli_fetch_array($link, $engine, "BOOL", NULL, NULL, 70);
+ func_mysqli_fetch_array($link, $engine, "BOOLEAN", 0, "0", 80);
+ func_mysqli_fetch_array($link, $engine, "BOOLEAN", NULL, NULL, 90);
+
+ func_mysqli_fetch_array($link, $engine, "SMALLINT", -32768, "-32768", 100);
+ func_mysqli_fetch_array($link, $engine, "SMALLINT", 32767, "32767", 110);
+ func_mysqli_fetch_array($link, $engine, "SMALLINT", NULL, NULL, 120);
+ func_mysqli_fetch_array($link, $engine, "SMALLINT UNSIGNED", 65535, "65535", 130);
+ func_mysqli_fetch_array($link, $engine, "SMALLINT UNSIGNED", NULL, NULL, 140);
+
+ func_mysqli_fetch_array($link, $engine, "MEDIUMINT", -8388608, "-8388608", 150);
+ func_mysqli_fetch_array($link, $engine, "MEDIUMINT", 8388607, "8388607", 160);
+ func_mysqli_fetch_array($link, $engine, "MEDIUMINT", NULL, NULL, 170);
+ func_mysqli_fetch_array($link, $engine, "MEDIUMINT UNSIGNED", 16777215, "16777215", 180);
+ func_mysqli_fetch_array($link, $engine, "MEDIUMINT UNSIGNED", NULL, NULL, 190);
+
+ func_mysqli_fetch_array($link, $engine, "INTEGER", -2147483648, "-2147483648", 200);
+ func_mysqli_fetch_array($link, $engine, "INTEGER", 2147483647, "2147483647", 210);
+ func_mysqli_fetch_array($link, $engine, "INTEGER", NULL, NULL, 220);
+ func_mysqli_fetch_array($link, $engine, "INTEGER UNSIGNED", "4294967295", "4294967295", 230);
+ func_mysqli_fetch_array($link, $engine, "INTEGER UNSIGNED", NULL, NULL, 240);
+
+ if ($IS_MYSQLND ||
+ ((mysqli_get_server_version($link) >= 51000) &&
+ (mysqli_get_client_version($link) >= 51000))) {
+ func_mysqli_fetch_array($link, $engine, "BIGINT", "-9223372036854775808", "-9223372036854775808", 250);
+ func_mysqli_fetch_array($link, $engine, "BIGINT", NULL, NULL, 260);
+ func_mysqli_fetch_array($link, $engine, "BIGINT UNSIGNED", "18446744073709551615", "18446744073709551615", 260);
+ func_mysqli_fetch_array($link, $engine, "BIGINT UNSIGNED", NULL, NULL, 280);
+ }
+
+ func_mysqli_fetch_array($link, $engine, "FLOAT", (string)(-9223372036854775808 - 1.1), "-9.22337e+18", 290, "/-9\.22337e\+?[0]?18/iu");
+ func_mysqli_fetch_array($link, $engine, "FLOAT", NULL, NULL, 300);
+ func_mysqli_fetch_array($link, $engine, "FLOAT UNSIGNED", (string)(18446744073709551615 + 1.1), "1.84467e+?19", 310, "/1\.84467e\+?[0]?19/iu");
+ func_mysqli_fetch_array($link, $engine, "FLOAT UNSIGNED ", NULL, NULL, 320);
+
+ func_mysqli_fetch_array($link, $engine, "DOUBLE(10,2)", "-99999999.99", "-99999999.99", 330);
+ func_mysqli_fetch_array($link, $engine, "DOUBLE(10,2)", NULL, NULL, 340);
+ func_mysqli_fetch_array($link, $engine, "DOUBLE(10,2) UNSIGNED", "99999999.99", "99999999.99", 350);
+ func_mysqli_fetch_array($link, $engine, "DOUBLE(10,2) UNSIGNED", NULL, NULL, 360);
+
+ func_mysqli_fetch_array($link, $engine, "DECIMAL(10,2)", "-99999999.99", "-99999999.99", 370);
+ func_mysqli_fetch_array($link, $engine, "DECIMAL(10,2)", NULL, NULL, 380);
+ func_mysqli_fetch_array($link, $engine, "DECIMAL(10,2)", "99999999.99", "99999999.99", 390);
+ func_mysqli_fetch_array($link, $engine, "DECIMAL(10,2)", NULL, NULL, 400);
+
+ // don't care about date() strict TZ warnings...
+ $date = @date('Y-m-d');
+ func_mysqli_fetch_array($link, $engine, "DATE",$date, $date, 410);
+ func_mysqli_fetch_array($link, $engine, "DATE NOT NULL",$date, $date, 420);
+ func_mysqli_fetch_array($link, $engine, "DATE", NULL, NULL, 430);
+
+ $date = @date('Y-m-d H:i:s');
+ func_mysqli_fetch_array($link, $engine, "DATETIME", $date, $date, 440);
+ func_mysqli_fetch_array($link, $engine, "DATETIME NOT NULL", $date, $date, 450);
+ func_mysqli_fetch_array($link, $engine, "DATETIME", NULL, NULL, 460);
+ func_mysqli_fetch_array($link, $engine, "TIMESTAMP", $date, $date, 470);
+
+ $date = @date('H:i:s');
+ func_mysqli_fetch_array($link, $engine, "TIME", $date, $date, 480);
+ func_mysqli_fetch_array($link, $engine, "TIME NOT NULL", $date, $date, 490);
+ func_mysqli_fetch_array($link, $engine, "TIME", NULL, NULL, 500);
+
+ func_mysqli_fetch_array($link, $engine, "YEAR", @date('Y'), @date('Y'), 510);
+ func_mysqli_fetch_array($link, $engine, "YEAR NOT NULL", @date('Y'), @date('Y'), 520);
+ func_mysqli_fetch_array($link, $engine, "YEAR", NULL, NULL, 530);
+
+ $string255 = func_mysqli_fetch_array_make_string(255);
+ func_mysqli_fetch_array($link, $engine, "CHAR(1)", "a", "a", 540);
+ func_mysqli_fetch_array($link, $engine, "CHAR(255)", $string255, $string255, 550);
+ func_mysqli_fetch_array($link, $engine, "CHAR(1) NOT NULL", "a", "a", 560);
+ func_mysqli_fetch_array($link, $engine, "CHAR(1)", NULL, NULL, 570);
+
+ $string65k = func_mysqli_fetch_array_make_string(65400);
+ func_mysqli_fetch_array($link, $engine, "VARCHAR(1)", "a", "a", 580);
+ func_mysqli_fetch_array($link, $engine, "VARCHAR(255)", $string255, $string255, 590);
+ func_mysqli_fetch_array($link, $engine, "VARCHAR(65400)", $string65k, $string65k, 600);
+ func_mysqli_fetch_array($link, $engine, "VARCHAR(1) NOT NULL", "a", "a", 610);
+ func_mysqli_fetch_array($link, $engine, "VARCHAR(1)", NULL, NULL, 620);
+
+ func_mysqli_fetch_array($link, $engine, "BINARY(1)", "a", "a", 630, null, true);
+ func_mysqli_fetch_array($link, $engine, "BINARY(2)", chr(0) . "a", chr(0) . "a", 640, null, true);
+ func_mysqli_fetch_array($link, $engine, "BINARY(1) NOT NULL", "b", "b", 650, null, true);
+ func_mysqli_fetch_array($link, $engine, "BINARY(1)", NULL, NULL, 660, null, true);
+
+ func_mysqli_fetch_array($link, $engine, "VARBINARY(1)", "a", "a", 670, null, true);
+ func_mysqli_fetch_array($link, $engine, "VARBINARY(2)", chr(0) . "a", chr(0) . "a", 680, null, true);
+ func_mysqli_fetch_array($link, $engine, "VARBINARY(1) NOT NULL", "b", "b", 690, null, true);
+ func_mysqli_fetch_array($link, $engine, "VARBINARY(1)", NULL, NULL, 700, null, true);
+
+ func_mysqli_fetch_array($link, $engine, "TINYBLOB", "a", "a", 710, null, true);
+ func_mysqli_fetch_array($link, $engine, "TINYBLOB", chr(0) . "a", chr(0) . "a", 720, null, true);
+ func_mysqli_fetch_array($link, $engine, "TINYBLOB NOT NULL", "b", "b", 730, null, true);
+ func_mysqli_fetch_array($link, $engine, "TINYBLOB", NULL, NULL, 740, null, true);
+
+ func_mysqli_fetch_array($link, $engine, "TINYTEXT", "a", "a", 750);
+ func_mysqli_fetch_array($link, $engine, "TINYTEXT NOT NULL", "a", "a", 760);
+ func_mysqli_fetch_array($link, $engine, "TINYTEXT", NULL, NULL, 770);
+
+ func_mysqli_fetch_array($link, $engine, "BLOB", "a", "a", 780, null, true);
+ func_mysqli_fetch_array($link, $engine, "BLOB", chr(0) . "a", chr(0) . "a", 780, null, true);
+ func_mysqli_fetch_array($link, $engine, "BLOB", NULL, NULL, 790, null, true);
+
+ func_mysqli_fetch_array($link, $engine, "TEXT", "a", "a", 800);
+ func_mysqli_fetch_array($link, $engine, "TEXT", chr(0) . "a", chr(0) . "a", 810);
+ func_mysqli_fetch_array($link, $engine, "TEXT", NULL, NULL, 820);
+
+ func_mysqli_fetch_array($link, $engine, "MEDIUMBLOB", "a", "a", 830, null, true);
+ func_mysqli_fetch_array($link, $engine, "MEDIUMBLOB", chr(0) . "a", chr(0) . "a", 840, null, true);
+ func_mysqli_fetch_array($link, $engine, "MEDIUMBLOB", NULL, NULL, 850, null, true);
+
+ func_mysqli_fetch_array($link, $engine, "MEDIUMTEXT", "a", "a", 860);
+ func_mysqli_fetch_array($link, $engine, "MEDIUMTEXT", chr(0) . "a", chr(0) . "a", 870);
+ func_mysqli_fetch_array($link, $engine, "MEDIUMTEXT", NULL, NULL, 880);
+
+ func_mysqli_fetch_array($link, $engine, "LONGBLOB", "a", "a", 890, null, true);
+ func_mysqli_fetch_array($link, $engine, "LONGTEXT", chr(0) . "a", chr(0) . "a", 900);
+ func_mysqli_fetch_array($link, $engine, "LONGBLOB", NULL, NULL, 910, null, true);
+
+ func_mysqli_fetch_array($link, $engine, "ENUM('a', 'b')", "a", "a", 920);
+ func_mysqli_fetch_array($link, $engine, "ENUM('a', 'b')", NULL, NULL, 930);
+
+ func_mysqli_fetch_array($link, $engine, "SET('a', 'b')", "a", "a", 940);
+ func_mysqli_fetch_array($link, $engine, "SET('a', 'b')", NULL, NULL, 950);
+
+ mysqli_close($link);
+
+ if (null !== ($tmp = mysqli_fetch_array($res, MYSQLI_ASSOC)))
+ printf("[015] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--EXPECTF--
+[005]
+array(4) {
+ [0]=>
+ %unicode|string%(1) "1"
+ [%u|b%"id"]=>
+ %unicode|string%(1) "1"
+ [1]=>
+ %unicode|string%(1) "a"
+ [%u|b%"label"]=>
+ %unicode|string%(1) "a"
+}
+[006]
+array(2) {
+ [0]=>
+ %unicode|string%(1) "2"
+ [1]=>
+ %unicode|string%(1) "b"
+}
+[007]
+array(4) {
+ [0]=>
+ %unicode|string%(1) "3"
+ [%u|b%"id"]=>
+ %unicode|string%(1) "3"
+ [1]=>
+ %unicode|string%(1) "c"
+ [%u|b%"label"]=>
+ %unicode|string%(1) "c"
+}
+[008]
+array(2) {
+ [%u|b%"id"]=>
+ %unicode|string%(1) "4"
+ [%u|b%"label"]=>
+ %unicode|string%(1) "d"
+}
+[009]
+array(4) {
+ [0]=>
+ %unicode|string%(1) "5"
+ [%u|b%"id"]=>
+ %unicode|string%(1) "5"
+ [1]=>
+ %unicode|string%(1) "e"
+ [%u|b%"label"]=>
+ %unicode|string%(1) "e"
+}
+[011]
+array(11) {
+ [0]=>
+ %unicode|string%(1) "1"
+ [%u|b%"a"]=>
+ %unicode|string%(1) "2"
+ [1]=>
+ %unicode|string%(1) "2"
+ [2]=>
+ %unicode|string%(1) "3"
+ [%u|b%"c"]=>
+ %unicode|string%(1) "3"
+ [3]=>
+ %unicode|string%(1) "4"
+ [%u|b%"C"]=>
+ %unicode|string%(1) "4"
+ [4]=>
+ NULL
+ [%u|b%"d"]=>
+ NULL
+ [5]=>
+ %unicode|string%(1) "1"
+ [%u|b%"e"]=>
+ %unicode|string%(1) "1"
+}
+
+Warning: mysqli_fetch_array(): The result type should be either MYSQLI_NUM, MYSQLI_ASSOC or MYSQLI_BOTH in %s on line %d
+
+Warning: mysqli_fetch_array(): The result type should be either MYSQLI_NUM, MYSQLI_ASSOC or MYSQLI_BOTH in %s on line %d
+
+Warning: mysqli_fetch_array(): Couldn't fetch mysqli_result in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_fetch_array_assoc.phpt b/ext/mysqli/tests/mysqli_fetch_array_assoc.phpt
new file mode 100644
index 0000000..957ca12
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_fetch_array_assoc.phpt
@@ -0,0 +1,49 @@
+--TEST--
+mysqli_fetch_array()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require('table.inc');
+
+ if (!$res = mysqli_query($link, "SELECT * FROM test ORDER BY id LIMIT 5")) {
+ printf("[001] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+ print "[002]\n";
+ var_dump(mysqli_fetch_array($res, MYSQLI_ASSOC));
+ mysqli_free_result($res);
+
+ if (!$res = mysqli_query($link, "SELECT id, label FROM test ORDER BY id LIMIT 5")) {
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+ print "[004]\n";
+ var_dump(mysqli_fetch_array($res, MYSQLI_ASSOC));
+ mysqli_free_result($res);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+[002]
+array(2) {
+ [%u|b%"id"]=>
+ %unicode|string%(1) "1"
+ [%u|b%"label"]=>
+ %unicode|string%(1) "a"
+}
+[004]
+array(2) {
+ [%u|b%"id"]=>
+ %unicode|string%(1) "1"
+ [%u|b%"label"]=>
+ %unicode|string%(1) "a"
+}
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_fetch_array_large.phpt b/ext/mysqli/tests/mysqli_fetch_array_large.phpt
new file mode 100644
index 0000000..3c6a0f0
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_fetch_array_large.phpt
@@ -0,0 +1,169 @@
+--TEST--
+mysqli_fetch_array() - large packages (to test compression)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--INI--
+memory_limit=-1
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ function mysqli_fetch_array_large($offset, $link, $package_size) {
+
+ /* we are aiming for maximum compression to test MYSQLI_CLIENT_COMPRESS */
+ $random_char = str_repeat('a', 255);
+ $sql = "INSERT INTO test(label) VALUES ";
+
+ while (strlen($sql) < ($package_size - 259))
+ $sql .= sprintf("('%s'), ", $random_char);
+
+ $sql = substr($sql, 0, -2);
+ $len = strlen($sql);
+ assert($len < $package_size);
+
+ if (!@mysqli_query($link, $sql)) {
+ if (1153 == mysqli_errno($link) || 2006 == mysqli_errno($link) || stristr(mysqli_error($link), 'max_allowed_packet'))
+ /*
+ myslqnd - [1153] Got a packet bigger than 'max_allowed_packet' bytes
+ libmysql -[2006] MySQL server has gone away
+ */
+ return false;
+
+ printf("[%03d + 1] len = %d, [%d] %s\n", $offset, $len, mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ /* buffered result set - let's hope we do not run into PHP memory limit... */
+ if (!$res = mysqli_query($link, "SELECT id, label FROM test")) {
+ printf("[%03d + 2] len = %d, [%d] %s\n", $offset, $len, mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ while ($row = mysqli_fetch_assoc($res)) {
+ if ($row['label'] != $random_char) {
+ printf("[%03d + 3] Wrong results - expecting '%s' got '%s', len = %d, [%d] %s\n",
+ $offset, $random_char, $row['label'], $len, mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+ }
+ mysqli_free_result($res);
+
+ if (!$stmt = mysqli_prepare($link, "SELECT id, label FROM test")) {
+ printf("[%03d + 4] len = %d, [%d] %s\n", $offset, $len, mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ /* unbuffered result set */
+ if (!mysqli_stmt_execute($stmt)) {
+ printf("[%03d + 5] len = %d, [%d] %s, [%d] %s\n", $offset, $len, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt), mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ $id = $label = NULL;
+ if (!mysqli_stmt_bind_result($stmt, $id, $label)) {
+ printf("[%03d + 6] len = %d, [%d] %s, [%d] %s\n", $offset, $len, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt), mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ while (mysqli_stmt_fetch($stmt)) {
+ if ($label != $random_char) {
+ printf("[%03d + 7] Wrong results - expecting '%s' got '%s', len = %d, [%d] %s\n",
+ $offset, $random_char, $label, $len, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ return false;
+ }
+ }
+
+ mysqli_stmt_free_result($stmt);
+ mysqli_stmt_close($stmt);
+
+ return true;
+ }
+
+ function parse_memory_limit($limit) {
+
+ $val = trim($limit);
+ $last = strtolower($val[strlen($val)-1]);
+
+ switch($last) {
+ // The 'G' modifier is available since PHP 5.1.0
+ case 'g':
+ $val *= 1024;
+ case 'm':
+ $val *= 1024;
+ case 'k':
+ $val *= 1024;
+ default:
+ break;
+ }
+ return $val;
+ }
+
+
+ function test_fetch($host, $user, $passwd, $db, $port, $socket, $engine, $flags = null) {
+
+ $link = mysqli_init();
+ if (!my_mysqli_real_connect($link, $host, $user, $passwd, $db, $port, $socket, $flags)) {
+ printf("[001] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+ return false;
+ }
+
+ if (!mysqli_query($link, "DROP TABLE IF EXISTS test") ||
+ !mysqli_query($link, sprintf("CREATE TABLE test(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, label VARCHAR(255)) ENGINE = %s", $engine))) {
+ printf("[002] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ $package_size = 524288;
+ $offset = 3;
+ $limit = (ini_get('memory_limit') > 0) ? parse_memory_limit(ini_get('memory_limit')) : pow(2, 32);
+
+ /* try to respect php.ini but make run time a soft limit */
+ $max_runtime = (ini_get('max_execution_time') > 0) ? ini_get('max_execution_time') : 30;
+ set_time_limit(0);
+
+ do {
+ if ($package_size > $limit) {
+ printf("stop: memory limit - %s vs. %s\n", $package_size, $limit);
+ break;
+ }
+
+ $start = microtime(true);
+ if (!mysqli_fetch_array_large($offset++, $link, $package_size)) {
+ printf("stop: packet size - %d\n", $package_size);
+ break;
+ }
+
+ $duration = microtime(true) - $start;
+ $max_runtime -= $duration;
+ if ($max_runtime < ($duration * 3)) {
+ /* likely the next iteration will not be within max_execution_time */
+ printf("stop: time limit - %2.2fs\n", $max_runtime);
+ break;
+ }
+
+ $package_size += $package_size;
+
+ } while (true);
+
+
+ mysqli_close($link);
+ return true;
+ }
+
+
+ test_fetch($host, $user, $passwd, $db, $port, $socket, $engine, null);
+ test_fetch($host, $user, $passwd, $db, $port, $socket, $engine, MYSQLI_CLIENT_COMPRESS);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+stop: %s
+stop: %s
+done!
diff --git a/ext/mysqli/tests/mysqli_fetch_array_many_rows.phpt b/ext/mysqli/tests/mysqli_fetch_array_many_rows.phpt
new file mode 100644
index 0000000..82e4d7b
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_fetch_array_many_rows.phpt
@@ -0,0 +1,115 @@
+--TEST--
+mysqli_fetch_array()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require("table.inc");
+
+ // do as much as we can do in 5 seconds
+ $start = microtime(true);
+ for ($id = 100, $start = microtime(true); (microtime(true) - $start) < 5; $id++) {
+ if (!mysqli_query($link, $sql = sprintf("INSERT INTO test(id, label) VALUES (%d, '%s')",
+ $id, mysqli_real_escape_string($link, chr(65 + ($id % 26)))))) {
+ printf("[001] %s failed: [%d] %s\n", $sql, mysqli_errno($link), mysqli_error($link));
+ break;
+ }
+ }
+
+ if (!$res = mysqli_query($link, 'SELECT id, label FROM test')) {
+ printf("[002] SELECT failed: [%d] %s\n", mysqli_errno($link), mysqli_errno($link));
+ }
+
+ while ($row = mysqli_fetch_array($res)) {
+ // overwrite results and check if the cache magic works
+ $row['label'] = NULL;
+ }
+ mysqli_free_result($res);
+
+ if (!$res = mysqli_query($link, 'SELECT id, label FROM test')) {
+ printf("[003] SELECT failed: [%d] %s\n", mysqli_errno($link), mysqli_errno($link));
+ }
+
+ $i = 0;
+ $results = array();
+ while ($row = mysqli_fetch_array($res, MYSQLI_BOTH)) {
+
+ // create copies and destroy later
+ $results[$i++] = &$row;
+ if ($i % 999) {
+ $results = array();
+ }
+
+ if ($row[0] < 0 || $row[0] > $id) {
+ printf("[004] Unexpected result row[0] = '%s' (range 0...%d), [%d] %s\n",
+ $row[0], $id, mysqli_errno($link), mysqli_error($link));
+ break;
+ }
+ if ($row[0] !== $row['id']) {
+ printf("[005] Unexpected result row[0] = '%s', row[id] = '%s', [%d] %s\n",
+ $row[0], $row[id], mysqli_errno($link), mysqli_error($link));
+ break;
+ }
+
+ $len = strlen($row[1]);
+ if (!is_string($row[1]) || $len == 0 || $len > 1) {
+ printf("[006] Unexpected result row[1] = '%s', [%d] %s\n",
+ $row[1], mysqli_errno($link), mysqli_error($link));
+ break;
+ }
+ if ($row[1] !== $row['label']) {
+ printf("[007] Unexpected result row[1] = '%s', row[label] = '%s', [%d] %s\n",
+ $row[1], $row['label'], mysqli_errno($link), mysqli_error($link));
+ break;
+ }
+
+ }
+ mysqli_free_result($res);
+
+ if (!$res = mysqli_query($link, 'SELECT id, label FROM test')) {
+ printf("[008] SELECT failed: [%d] %s\n", mysqli_errno($link), mysqli_errno($link));
+ }
+
+ while ($row = mysqli_fetch_array($res, MYSQLI_ASSOC)) {
+ // overwrite results and check if the cache magic works
+ $row['label'] = NULL;
+ }
+ mysqli_free_result($res);
+
+ if (!$res = mysqli_query($link, 'SELECT count(*) AS num FROM test')) {
+ printf("[009] SELECT failed: [%d] %s\n", mysqli_errno($link), mysqli_errno($link));
+ }
+ $row = mysqli_fetch_assoc($res);
+ $num = $row['num'];
+ mysqli_free_result($res);
+
+ if (!$res = mysqli_query($link, 'SELECT id, label FROM test')) {
+ printf("[010] SELECT failed: [%d] %s\n", mysqli_errno($link), mysqli_errno($link));
+ }
+
+ $i = 0;
+ while ($row = mysqli_fetch_array($res, MYSQLI_NUM)) {
+ // overwrite results and check if the cache magic works
+ $row[0] = NULL;
+ $i++;
+ }
+ mysqli_free_result($res);
+
+ if ($i != $num)
+ printf("[011] Expecting %d results, got %d results, [%d] %s\n",
+ $num, $i, mysqli_errno($link), mysqli_error($link));
+
+ mysqli_close($link);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_fetch_array_oo.phpt b/ext/mysqli/tests/mysqli_fetch_array_oo.phpt
new file mode 100644
index 0000000..21d78ae
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_fetch_array_oo.phpt
@@ -0,0 +1,362 @@
+--TEST--
+mysqli->fetch_array()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ require('table.inc');
+ if (!$mysqli = new my_mysqli($host, $user, $passwd, $db, $port, $socket))
+ printf("[001] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ if (!$res = $mysqli->query("SELECT * FROM test ORDER BY id LIMIT 5")) {
+ printf("[004] [%d] %s\n", $mysqli->errno, $mysqli->error);
+ }
+
+ print "[005]\n";
+ var_dump($res->fetch_array());
+
+ print "[006]\n";
+ var_dump($res->fetch_array(MYSQLI_NUM));
+
+ print "[007]\n";
+ var_dump($res->fetch_array(MYSQLI_BOTH));
+
+ print "[008]\n";
+ var_dump($res->fetch_array(MYSQLI_ASSOC));
+
+ print "[009]\n";
+ var_dump($res->fetch_array());
+
+ $res->free_result();
+
+ if (!$res = $mysqli->query("SELECT 1 AS a, 2 AS a, 3 AS c, 4 AS C, NULL AS d, true AS e")) {
+ printf("[010] Cannot run query, [%d] %s\n", $mysqli->errno, $$mysqli->error);
+ }
+ print "[011]\n";
+ var_dump($res->fetch_array(MYSQLI_BOTH));
+
+ $res->free_result();
+ if (!$res = $mysqli->query("SELECT 1 AS a, 2 AS b, 3 AS c, 4 AS C")) {
+ printf("[012] Cannot run query, [%d] %s\n",
+ $mysqli->errno, $$mysqli->error);
+ exit(1);
+ }
+
+ do {
+ $illegal_mode = mt_rand(-10000, 10000);
+ } while (in_array($illegal_mode, array(MYSQLI_ASSOC, MYSQLI_NUM, MYSQLI_BOTH)));
+ // NOTE: for BC reasons with ext/mysql, ext/mysqli accepts invalid result modes.
+ $tmp = $res->fetch_array($illegal_mode);
+ if (false !== $tmp)
+ printf("[013] Expecting boolean/false although, got %s/%s. [%d] %s\n",
+ gettype($tmp), $tmp, $mysqli->errno, $mysqli->error);
+
+ $tmp = $res->fetch_array($illegal_mode);
+ if (false !== $tmp)
+ printf("[014] Expecting boolean/false, got %s/%s. [%d] %s\n",
+ gettype($tmp), $tmp, $mysqli->errno, $mysqli->error);
+
+ $res->free_result();
+
+ function func_mysqli_fetch_array($mysqli, $engine, $sql_type, $sql_value, $php_value, $offset, $regexp_comparison = NULL) {
+
+ if (!$mysqli->query("DROP TABLE IF EXISTS test")) {
+ printf("[%04d] [%d] %s\n", $offset, $mysqli->errno, $mysqli->error);
+ return false;
+ }
+
+ if (!$mysqli->query($sql = sprintf("CREATE TABLE test(id INT NOT NULL, label %s, PRIMARY KEY(id)) ENGINE = %s", $sql_type, $engine))) {
+ // don't bail, engine might not support the datatype
+ return false;
+ }
+
+ if (is_null($php_value)) {
+ if (!$mysqli->query($sql = sprintf("INSERT INTO test(id, label) VALUES (1, NULL)"))) {
+ printf("[%04d] [%d] %s\n", $offset + 1, $mysqli->errno, $mysqli->error);
+ return false;
+ }
+ } else {
+ if (is_string($sql_value)) {
+ if (!$mysqli->query($sql = "INSERT INTO test(id, label) VALUES (1, '" . $sql_value . "')")) {
+ printf("[%04ds] [%d] %s - %s\n", $offset + 1, $mysqli->errno, $mysqli->error, $sql);
+ return false;
+ }
+ } else {
+ if (!$mysqli->query($sql = sprintf("INSERT INTO test(id, label) VALUES (1, '%d')", $sql_value))) {
+ printf("[%04di] [%d] %s\n", $offset + 1, $mysqli->errno, $mysqli->error);
+ return false;
+ }
+ }
+ }
+
+ if (!$res = $mysqli->query("SELECT id, label FROM test")) {
+ printf("[%04d] [%d] %s\n", $offset + 2, $mysqli->errno, $mysqli->error);
+ return false;
+ }
+
+ if (!$row = $res->fetch_array(MYSQLI_BOTH)) {
+ printf("[%04d] [%d] %s\n", $offset + 3, $mysqli->errno, $mysqli->error);
+ return false;
+ }
+ $fields = mysqli_fetch_fields($res);
+
+ if (!(gettype($php_value)=="unicode" && ($fields[1]->flags & 128))) {
+ if ($regexp_comparison) {
+ if (!preg_match($regexp_comparison, (string)$row['label']) || !preg_match($regexp_comparison, (string)$row[1])) {
+ printf("[%04d] Expecting %s/%s [reg exp = %s], got %s/%s resp. %s/%s. [%d] %s\n", $offset + 4,
+ gettype($php_value), $php_value, $regexp_comparison,
+ gettype($row[1]), $row[1],
+ gettype($row['label']), $row['label'], $mysqli->errno, $mysqli->error);
+ return false;
+ }
+ } else {
+ if (($row['label'] !== $php_value) || ($row[1] != $php_value)) {
+ printf("[%04d] Expecting %s/%s, got %s/%s resp. %s/%s. [%d] %s\n", $offset + 4,
+ gettype($php_value), $php_value,
+ gettype($row[1]), $row[1],
+ gettype($row['label']), $row['label'], $mysqli->errno, $mysqli->error);
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ function func_mysqli_fetch_array_make_string($len) {
+
+ $ret = '';
+ for ($i = 0; $i < $len; $i++)
+ $ret .= chr(mt_rand(65, 90));
+
+ return $ret;
+ }
+
+ func_mysqli_fetch_array($mysqli, $engine, "TINYINT", -11, "-11", 20);
+ func_mysqli_fetch_array($mysqli, $engine, "TINYINT", NULL, NULL, 30);
+ func_mysqli_fetch_array($mysqli, $engine, "TINYINT UNSIGNED", 1, "1", 40);
+ func_mysqli_fetch_array($mysqli, $engine, "TINYINT UNSIGNED", NULL, NULL, 50);
+
+ func_mysqli_fetch_array($mysqli, $engine, "BOOL", 1, "1", 60);
+ func_mysqli_fetch_array($mysqli, $engine, "BOOL", NULL, NULL, 70);
+ func_mysqli_fetch_array($mysqli, $engine, "BOOLEAN", 0, "0", 80);
+ func_mysqli_fetch_array($mysqli, $engine, "BOOLEAN", NULL, NULL, 90);
+
+ func_mysqli_fetch_array($mysqli, $engine, "SMALLINT", -32768, "-32768", 100);
+ func_mysqli_fetch_array($mysqli, $engine, "SMALLINT", 32767, "32767", 110);
+ func_mysqli_fetch_array($mysqli, $engine, "SMALLINT", NULL, NULL, 120);
+ func_mysqli_fetch_array($mysqli, $engine, "SMALLINT UNSIGNED", 65535, "65535", 130);
+ func_mysqli_fetch_array($mysqli, $engine, "SMALLINT UNSIGNED", NULL, NULL, 140);
+
+ func_mysqli_fetch_array($mysqli, $engine, "MEDIUMINT", -8388608, "-8388608", 150);
+ func_mysqli_fetch_array($mysqli, $engine, "MEDIUMINT", 8388607, "8388607", 160);
+ func_mysqli_fetch_array($mysqli, $engine, "MEDIUMINT", NULL, NULL, 170);
+ func_mysqli_fetch_array($mysqli, $engine, "MEDIUMINT UNSIGNED", 16777215, "16777215", 180);
+ func_mysqli_fetch_array($mysqli, $engine, "MEDIUMINT UNSIGNED", NULL, NULL, 190);
+
+ func_mysqli_fetch_array($mysqli, $engine, "INTEGER", -2147483648, "-2147483648", 200);
+ func_mysqli_fetch_array($mysqli, $engine, "INTEGER", 2147483647, "2147483647", 210);
+ func_mysqli_fetch_array($mysqli, $engine, "INTEGER", NULL, NULL, 220);
+ func_mysqli_fetch_array($mysqli, $engine, "INTEGER UNSIGNED", "4294967295", "4294967295", 230);
+ func_mysqli_fetch_array($mysqli, $engine, "INTEGER UNSIGNED", NULL, NULL, 240);
+
+ if ($IS_MYSQLND ||
+ ((mysqli_get_server_version($link) >= 51000) &&
+ (mysqli_get_client_version($link) >= 51000))) {
+ func_mysqli_fetch_array($mysqli, $engine, "BIGINT", "-9223372036854775808", "-9223372036854775808", 250);
+ func_mysqli_fetch_array($mysqli, $engine, "BIGINT", NULL, NULL, 260);
+ func_mysqli_fetch_array($mysqli, $engine, "BIGINT UNSIGNED", "18446744073709551615", "18446744073709551615", 270);
+ func_mysqli_fetch_array($mysqli, $engine, "BIGINT UNSIGNED", NULL, NULL, 280);
+ }
+
+ func_mysqli_fetch_array($mysqli, $engine, "FLOAT", (string)(-9223372036854775808 - 1.1), "-9.22337e+18", 290, "/-9\.22337e\+?[0]?18/iu");
+ func_mysqli_fetch_array($mysqli, $engine, "FLOAT", NULL, NULL, 300);
+ func_mysqli_fetch_array($mysqli, $engine, "FLOAT UNSIGNED", (string)(18446744073709551615 + 1.1), "1.84467e+?19", 310, "/1\.84467e\+?[0]?19/iu");
+ func_mysqli_fetch_array($mysqli, $engine, "FLOAT UNSIGNED ", NULL, NULL, 320);
+
+ func_mysqli_fetch_array($mysqli, $engine, "DOUBLE(10,2)", "-99999999.99", "-99999999.99", 330);
+ func_mysqli_fetch_array($mysqli, $engine, "DOUBLE(10,2)", NULL, NULL, 340);
+ func_mysqli_fetch_array($mysqli, $engine, "DOUBLE(10,2) UNSIGNED", "99999999.99", "99999999.99", 350);
+ func_mysqli_fetch_array($mysqli, $engine, "DOUBLE(10,2) UNSIGNED", NULL, NULL, 360);
+ func_mysqli_fetch_array($mysqli, $engine, "DECIMAL(10,2)", "-99999999.99", "-99999999.99", 370);
+ func_mysqli_fetch_array($mysqli, $engine, "DECIMAL(10,2)", NULL, NULL, 380);
+ func_mysqli_fetch_array($mysqli, $engine, "DECIMAL(10,2)", "99999999.99", "99999999.99", 390);
+ func_mysqli_fetch_array($mysqli, $engine, "DECIMAL(10,2)", NULL, NULL, 400);
+
+ // don't care about date() strict TZ warnings...
+ $date = @date('Y-m-d');
+ func_mysqli_fetch_array($mysqli, $engine, "DATE",$date, $date, 410);
+ func_mysqli_fetch_array($mysqli, $engine, "DATE NOT NULL",$date, $date, 420);
+ func_mysqli_fetch_array($mysqli, $engine, "DATE", NULL, NULL, 430);
+
+ $date = @date('Y-m-d H:i:s');
+ func_mysqli_fetch_array($mysqli, $engine, "DATETIME", $date, $date, 440);
+ func_mysqli_fetch_array($mysqli, $engine, "DATETIME NOT NULL", $date, $date, 450);
+ func_mysqli_fetch_array($mysqli, $engine, "DATETIME", NULL, NULL, 460);
+ func_mysqli_fetch_array($mysqli, $engine, "TIMESTAMP", $date, $date, 470);
+ $date = @date('H:i:s');
+ func_mysqli_fetch_array($mysqli, $engine, "TIME", $date, $date, 480);
+ func_mysqli_fetch_array($mysqli, $engine, "TIME NOT NULL", $date, $date, 490);
+ func_mysqli_fetch_array($mysqli, $engine, "TIME", NULL, NULL, 500);
+ func_mysqli_fetch_array($mysqli, $engine, "YEAR", @date('Y'), @date('Y'), 510);
+ func_mysqli_fetch_array($mysqli, $engine, "YEAR NOT NULL", @date('Y'), @date('Y'), 520);
+ func_mysqli_fetch_array($mysqli, $engine, "YEAR", NULL, NULL, 530);
+
+ $string255 = func_mysqli_fetch_array_make_string(255);
+ func_mysqli_fetch_array($mysqli, $engine, "CHAR(1)", "a", "a", 540);
+ func_mysqli_fetch_array($mysqli, $engine, "CHAR(255)", $string255, $string255, 550);
+ func_mysqli_fetch_array($mysqli, $engine, "CHAR(1) NOT NULL", "a", "a", 560);
+ func_mysqli_fetch_array($mysqli, $engine, "CHAR(1)", NULL, NULL, 570);
+
+ $string65k = func_mysqli_fetch_array_make_string(65400);
+ func_mysqli_fetch_array($mysqli, $engine, "VARCHAR(1)", "a", "a", 580);
+ func_mysqli_fetch_array($mysqli, $engine, "VARCHAR(255)", $string255, $string255, 590);
+ func_mysqli_fetch_array($mysqli, $engine, "VARCHAR(65400)", $string65k, $string65k, 600);
+ func_mysqli_fetch_array($mysqli, $engine, "VARCHAR(1) NOT NULL", "a", "a", 610);
+ func_mysqli_fetch_array($mysqli, $engine, "VARCHAR(1)", NULL, NULL, 620);
+
+ func_mysqli_fetch_array($mysqli, $engine, "BINARY(1)", "a", "a", 630);
+ func_mysqli_fetch_array($mysqli, $engine, "BINARY(2)", chr(0) . "a", chr(0) . "a", 640);
+ func_mysqli_fetch_array($mysqli, $engine, "BINARY(1) NOT NULL", "b", "b", 650);
+ func_mysqli_fetch_array($mysqli, $engine, "BINARY(1)", NULL, NULL, 660);
+
+ func_mysqli_fetch_array($mysqli, $engine, "VARBINARY(1)", "a", "a", 670);
+ func_mysqli_fetch_array($mysqli, $engine, "VARBINARY(2)", chr(0) . "a", chr(0) . "a", 680);
+ func_mysqli_fetch_array($mysqli, $engine, "VARBINARY(1) NOT NULL", "b", "b", 690);
+ func_mysqli_fetch_array($mysqli, $engine, "VARBINARY(1)", NULL, NULL, 700);
+
+ func_mysqli_fetch_array($mysqli, $engine, "TINYBLOB", "a", "a", 710);
+ func_mysqli_fetch_array($mysqli, $engine, "TINYBLOB", chr(0) . "a", chr(0) . "a", 720);
+ func_mysqli_fetch_array($mysqli, $engine, "TINYBLOB NOT NULL", "b", "b", 730);
+ func_mysqli_fetch_array($mysqli, $engine, "TINYBLOB", NULL, NULL, 740);
+
+ func_mysqli_fetch_array($mysqli, $engine, "TINYTEXT", "a", "a", 750);
+ func_mysqli_fetch_array($mysqli, $engine, "TINYTEXT NOT NULL", "a", "a", 760);
+ func_mysqli_fetch_array($mysqli, $engine, "TINYTEXT", NULL, NULL, 770);
+
+ func_mysqli_fetch_array($mysqli, $engine, "BLOB", "a", "a", 780);
+ func_mysqli_fetch_array($mysqli, $engine, "BLOB", chr(0) . "a", chr(0) . "a", 780);
+ func_mysqli_fetch_array($mysqli, $engine, "BLOB", NULL, NULL, 790);
+
+ func_mysqli_fetch_array($mysqli, $engine, "TEXT", "a", "a", 800);
+ func_mysqli_fetch_array($mysqli, $engine, "TEXT", chr(0) . "a", chr(0) . "a", 810);
+ func_mysqli_fetch_array($mysqli, $engine, "TEXT", NULL, NULL, 820);
+
+ func_mysqli_fetch_array($mysqli, $engine, "MEDIUMBLOB", "a", "a", 830);
+ func_mysqli_fetch_array($mysqli, $engine, "MEDIUMBLOB", chr(0) . "a", chr(0) . "a", 840);
+ func_mysqli_fetch_array($mysqli, $engine, "MEDIUMBLOB", NULL, NULL, 850);
+
+ func_mysqli_fetch_array($mysqli, $engine, "MEDIUMTEXT", "a", "a", 860);
+ func_mysqli_fetch_array($mysqli, $engine, "MEDIUMTEXT", chr(0) . "a", chr(0) . "a", 870);
+ func_mysqli_fetch_array($mysqli, $engine, "MEDIUMTEXT", NULL, NULL, 880);
+
+ func_mysqli_fetch_array($mysqli, $engine, "LONGBLOB", "a", "a", 890);
+ func_mysqli_fetch_array($mysqli, $engine, "LONGTEXT", chr(0) . "a", chr(0) . "a", 900);
+ func_mysqli_fetch_array($mysqli, $engine, "LONGBLOB", NULL, NULL, 910);
+
+ func_mysqli_fetch_array($mysqli, $engine, "ENUM('a', 'b')", "a", "a", 920);
+ func_mysqli_fetch_array($mysqli, $engine, "ENUM('a', 'b')", NULL, NULL, 930);
+
+ func_mysqli_fetch_array($mysqli, $engine, "SET('a', 'b')", "a", "a", 940);
+ func_mysqli_fetch_array($mysqli, $engine, "SET('a', 'b')", NULL, NULL, 950);
+
+ $mysqli->close();
+
+ if (null !== ($tmp = $res->fetch_array(MYSQLI_ASSOC)))
+ printf("[015] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+[005]
+array(4) {
+ [0]=>
+ %unicode|string%(1) "1"
+ [%u|b%"id"]=>
+ %unicode|string%(1) "1"
+ [1]=>
+ %unicode|string%(1) "a"
+ [%u|b%"label"]=>
+ %unicode|string%(1) "a"
+}
+[006]
+array(2) {
+ [0]=>
+ %unicode|string%(1) "2"
+ [1]=>
+ %unicode|string%(1) "b"
+}
+[007]
+array(4) {
+ [0]=>
+ %unicode|string%(1) "3"
+ [%u|b%"id"]=>
+ %unicode|string%(1) "3"
+ [1]=>
+ %unicode|string%(1) "c"
+ [%u|b%"label"]=>
+ %unicode|string%(1) "c"
+}
+[008]
+array(2) {
+ [%u|b%"id"]=>
+ %unicode|string%(1) "4"
+ [%u|b%"label"]=>
+ %unicode|string%(1) "d"
+}
+[009]
+array(4) {
+ [0]=>
+ %unicode|string%(1) "5"
+ [%u|b%"id"]=>
+ %unicode|string%(1) "5"
+ [1]=>
+ %unicode|string%(1) "e"
+ [%u|b%"label"]=>
+ %unicode|string%(1) "e"
+}
+[011]
+array(11) {
+ [0]=>
+ %unicode|string%(1) "1"
+ [%u|b%"a"]=>
+ %unicode|string%(1) "2"
+ [1]=>
+ %unicode|string%(1) "2"
+ [2]=>
+ %unicode|string%(1) "3"
+ [%u|b%"c"]=>
+ %unicode|string%(1) "3"
+ [3]=>
+ %unicode|string%(1) "4"
+ [%u|b%"C"]=>
+ %unicode|string%(1) "4"
+ [4]=>
+ NULL
+ [%u|b%"d"]=>
+ NULL
+ [5]=>
+ %unicode|string%(1) "1"
+ [%u|b%"e"]=>
+ %unicode|string%(1) "1"
+}
+
+Warning: mysqli_result::fetch_array(): The result type should be either MYSQLI_NUM, MYSQLI_ASSOC or MYSQLI_BOTH in %s on line %d
+
+Warning: mysqli_result::fetch_array(): The result type should be either MYSQLI_NUM, MYSQLI_ASSOC or MYSQLI_BOTH in %s on line %d
+
+Warning: mysqli_result::fetch_array(): Couldn't fetch mysqli_result in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_fetch_assoc.phpt b/ext/mysqli/tests/mysqli_fetch_assoc.phpt
new file mode 100644
index 0000000..edf143b
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_fetch_assoc.phpt
@@ -0,0 +1,119 @@
+--TEST--
+mysqli_fetch_assoc()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ // Note: no SQL type tests, internally the same function gets used as for mysqli_fetch_array() which does a lot of SQL type test
+
+ if (!is_null($tmp = @mysqli_fetch_assoc()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_fetch_assoc($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+ if (!$res = mysqli_query($link, "SELECT id, label FROM test ORDER BY id LIMIT 1")) {
+ printf("[004] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ print "[005]\n";
+ var_dump(mysqli_fetch_assoc($res));
+
+ print "[006]\n";
+ var_dump(mysqli_fetch_assoc($res));
+
+ mysqli_free_result($res);
+
+ if (!$res = mysqli_query($link, "SELECT
+ 1 AS a,
+ 2 AS a,
+ 3 AS c,
+ 4 AS C,
+ NULL AS d,
+ true AS e,
+ 5 AS '-1',
+ 6 AS '-10',
+ 7 AS '-100',
+ 8 AS '-1000',
+ 9 AS '10000',
+ 'a' AS '100000',
+ 'b' AS '1000000',
+ 'c' AS '9',
+ 'd' AS '9',
+ 'e' AS '01',
+ 'f' AS '-02'
+ ")) {
+ printf("[007] Cannot run query, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+ print "[008]\n";
+ var_dump(mysqli_fetch_assoc($res));
+
+ mysqli_free_result($res);
+
+ if (NULL !== ($tmp = mysqli_fetch_assoc($res)))
+ printf("[008] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_close($link);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+[005]
+array(2) {
+ [%u|b%"id"]=>
+ %unicode|string%(1) "1"
+ [%u|b%"label"]=>
+ %unicode|string%(1) "a"
+}
+[006]
+NULL
+[008]
+array(15) {
+ [%u|b%"a"]=>
+ %unicode|string%(1) "2"
+ [%u|b%"c"]=>
+ %unicode|string%(1) "3"
+ [%u|b%"C"]=>
+ %unicode|string%(1) "4"
+ [%u|b%"d"]=>
+ NULL
+ [%u|b%"e"]=>
+ %unicode|string%(1) "1"
+ [-1]=>
+ %unicode|string%(1) "5"
+ [-10]=>
+ %unicode|string%(1) "6"
+ [-100]=>
+ %unicode|string%(1) "7"
+ [-1000]=>
+ %unicode|string%(1) "8"
+ [10000]=>
+ %unicode|string%(1) "9"
+ [100000]=>
+ %unicode|string%(1) "a"
+ [1000000]=>
+ %unicode|string%(1) "b"
+ [9]=>
+ %unicode|string%(1) "d"
+ [%u|b%"01"]=>
+ %unicode|string%(1) "e"
+ [%u|b%"-02"]=>
+ %unicode|string%(1) "f"
+}
+
+Warning: mysqli_fetch_assoc(): Couldn't fetch mysqli_result in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_fetch_assoc_bit.phpt b/ext/mysqli/tests/mysqli_fetch_assoc_bit.phpt
new file mode 100644
index 0000000..d9bdcfa
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_fetch_assoc_bit.phpt
@@ -0,0 +1,117 @@
+--TEST--
+mysqli_fetch_assoc() - BIT
+--SKIPIF--
+<?php
+ require_once('skipif.inc');
+ require_once('skipifemb.inc');
+ require_once('skipifconnectfailure.inc');
+
+ require_once('connect.inc');
+ require_once('table.inc');
+ if (mysqli_get_server_version($link) < 50003)
+ // b'001' syntax not supported before 5.0.3
+ die("skip Syntax used for test not supported with MySQL Server before 5.0.3");
+ if (!$IS_MYSQLND && (mysqli_get_client_version() < 50003))
+ // better don't trust libmysql before 5.0.3
+ die("skip Syntax used for test not supported with MySQL Server before 5.0.3");
+?>
+--FILE--
+<?php
+ require('connect.inc');
+
+ function dec32bin($dec, $bits) {
+
+ $maxval = pow(2, $bits);
+ $bin = '';
+ for ($bitval = $maxval; $bitval >= 1; $bitval = $bitval / 2) {
+ if (($dec / $bitval) >= 1) {
+ $bin .= '1';
+ $dec -= $bitval;
+ } else {
+ $bin .= '0';
+ }
+ }
+ return $bin;
+ }
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[001] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ for ($bits = 1; $bits <= 46; $bits++) {
+ if (1 == $bits)
+ $max_value = 1;
+ else
+ $max_value = pow(2, $bits) - 1;
+ $tests = 0;
+ if (!mysqli_query($link, "DROP TABLE IF EXISTS test") ||
+ !mysqli_query($link, $sql = sprintf('CREATE TABLE test(id BIGINT, bit_value BIT(%d) NOT NULL, bit_null BIT(%d) DEFAULT NULL) ENGINE="%s"', $bits, $bits, $engine)))
+ printf("[002 - %d] [%d] %s\n",$bits, mysqli_errno($link), mysqli_error($link));
+
+ $tests = 0;
+ $rand_max = mt_getrandmax();
+ while ($tests < 10) {
+
+ $tests++;
+ if (1 == $tests)
+ $value = 0;
+ else if (2 == $tests)
+ $value = $max_value;
+ else {
+ if ($max_value > $rand_max) {
+ $max_loops = floor($max_value/$rand_max);
+ $num_loops = mt_rand(1, $max_loops);
+ $value = 0;
+ for ($i = 0; $i < $num_loops; $i++)
+ $value += mt_rand(0, $rand_max);
+ } else {
+ $value = mt_rand(0, $max_value);
+ }
+ }
+
+ $bin = ($bits < 32) ? decbin($value) : dec32bin($value, $bits);
+ $sql = sprintf("INSERT INTO test(id, bit_value) VALUES (%s, b'%s')", $value, $bin);
+ for ($i = 0; ($i < strlen($bin)) && ($bin[$i] == '0'); $i++)
+ ;
+ $bin2 = substr($bin, $i, strlen($bin));
+
+ if (!mysqli_query($link, $sql))
+ printf("[003 - %d] [%d] %s\n", $bits, mysqli_errno($link), mysqli_error($link));
+
+ $sql = sprintf("SELECT id, BIN(bit_value) AS _bin, bit_value + 0 AS _bit_value0, bit_value, bit_null FROM test WHERE id = %s", $value);
+ if (!$res = mysqli_query($link, $sql))
+ printf("[004 - %d] [%d] %s\n", $bits, mysqli_errno($link), mysqli_error($link));
+
+ if (!$row = mysqli_fetch_assoc($res))
+ printf("[005 - %d] [%d] %s\n", $bits, mysqli_errno($link), mysqli_error($link));
+
+ if (($value != $row['id']) || (($bin != $row['_bin']) && ($bin2 != $row['_bin']))) {
+ debug_zval_dump($row);
+ printf("[006 - %d] Insert of %s in BIT(%d) column might have failed. id = %s, bin = %s (%s/%s)\n",
+ $bits, $value, $bits, $row['id'], $row['_bin'], $bin, $bin2);
+ break;
+ }
+ if ($value != $row['bit_value']) {
+ debug_zval_dump($row);
+ printf("%10s %64s\n%10s %64s\n", '_bin', $row['_bin'], 'insert', $bin);
+ printf("[007 - %d] Expecting %s got %s\n", $bits, $value, $row['bit_value']);
+ break;
+ }
+
+ if (null !== $row['bit_null']) {
+ debug_zval_dump($row);
+ printf("[008 - %d] Expecting null got %s/%s\n", $bits, gettype($row['bit_value']), $row['bit_value']);
+ break;
+ }
+ }
+ }
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+done!
diff --git a/ext/mysqli/tests/mysqli_fetch_assoc_no_alias.phpt b/ext/mysqli/tests/mysqli_fetch_assoc_no_alias.phpt
new file mode 100644
index 0000000..a273b73
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_fetch_assoc_no_alias.phpt
@@ -0,0 +1,142 @@
+--TEST--
+mysqli_fetch_assoc()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require('table.inc');
+
+ if (!$res = mysqli_query($link, "SELECT 1, 2")) {
+ printf("[001] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+ print "[002]\n";
+ var_dump(mysqli_fetch_assoc($res));
+ mysqli_free_result($res);
+
+ if (!$res = mysqli_query($link, "SELECT 1 AS a, 2")) {
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+ print "[004]\n";
+ var_dump(mysqli_fetch_assoc($res));
+ mysqli_free_result($res);
+
+ if (!$res = mysqli_query($link, "SELECT 1 AS a, 2, 2 as '2'")) {
+ printf("[005] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+ print "[006]\n";
+ var_dump(mysqli_fetch_assoc($res));
+ mysqli_free_result($res);
+
+ if (!$res = mysqli_query($link, "SELECT 1 AS a, 2 as '2', 2")) {
+ printf("[007] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+ print "[008]\n";
+ var_dump(mysqli_fetch_assoc($res));
+ mysqli_free_result($res);
+
+ /* Now do it with unbuffered queries */
+ if (!$res = mysqli_real_query($link, "SELECT 1, 2")) {
+ printf("[009] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+ if (!$res = mysqli_use_result($link)) {
+ printf("[010] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+ print "[011]\n";
+ var_dump(mysqli_fetch_assoc($res));
+ mysqli_free_result($res);
+
+ if (!$res = mysqli_real_query($link, "SELECT 1 AS a, 2")) {
+ printf("[012] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+ if (!$res = mysqli_use_result($link)) {
+ printf("[013] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+ print "[014]\n";
+ var_dump(mysqli_fetch_assoc($res));
+ mysqli_free_result($res);
+
+ if (!$res = mysqli_real_query($link, "SELECT 1 AS a, 2, 2 as '2'")) {
+ printf("[015] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+ if (!$res = mysqli_use_result($link)) {
+ printf("[016] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+ print "[017]\n";
+ var_dump(mysqli_fetch_assoc($res));
+ mysqli_free_result($res);
+
+ if (!$res = mysqli_real_query($link, "SELECT 1 AS a, 2 as '2', 2")) {
+ printf("[015] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+ if (!$res = mysqli_use_result($link)) {
+ printf("[016] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+ print "[017]\n";
+ var_dump(mysqli_fetch_assoc($res));
+ mysqli_free_result($res);
+ mysqli_close($link);
+
+ print "done!";
+?>
+--EXPECTF--
+[002]
+array(2) {
+ [1]=>
+ %unicode|string%(1) "1"
+ [2]=>
+ %unicode|string%(1) "2"
+}
+[004]
+array(2) {
+ [%u|b%"a"]=>
+ %unicode|string%(1) "1"
+ [2]=>
+ %unicode|string%(1) "2"
+}
+[006]
+array(2) {
+ [%u|b%"a"]=>
+ %unicode|string%(1) "1"
+ [2]=>
+ %unicode|string%(1) "2"
+}
+[008]
+array(2) {
+ [%u|b%"a"]=>
+ %unicode|string%(1) "1"
+ [2]=>
+ %unicode|string%(1) "2"
+}
+[011]
+array(2) {
+ [1]=>
+ %unicode|string%(1) "1"
+ [2]=>
+ %unicode|string%(1) "2"
+}
+[014]
+array(2) {
+ [%u|b%"a"]=>
+ %s(1) "1"
+ [2]=>
+ %s(1) "2"
+}
+[017]
+array(2) {
+ [%u|b%"a"]=>
+ %unicode|string%(1) "1"
+ [2]=>
+ %unicode|string%(1) "2"
+}
+[017]
+array(2) {
+ [%u|b%"a"]=>
+ %unicode|string%(1) "1"
+ [2]=>
+ %unicode|string%(1) "2"
+}
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_fetch_assoc_no_alias_utf8.phpt b/ext/mysqli/tests/mysqli_fetch_assoc_no_alias_utf8.phpt
new file mode 100644
index 0000000..fa00ecd
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_fetch_assoc_no_alias_utf8.phpt
@@ -0,0 +1,164 @@
+--TEST--
+mysqli_fetch_assoc() - utf8
+--SKIPIF--
+<?php
+ require_once('skipif.inc');
+ require_once('skipifemb.inc');
+ require_once('skipifconnectfailure.inc');
+ require_once("connect.inc");
+
+ if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ die("skip Cannot connect to server to check charsets");
+
+ if (!$res = mysqli_query($link, "SHOW CHARACTER SET LIKE 'UTF8'"))
+ die("skip Cannot run SHOW CHARACTER SET to check charsets");
+
+ if (!$tmp = mysqli_fetch_assoc($res))
+ die("skip Looks like UTF8 is not available on the server");
+
+ if (strtolower($tmp['Charset']) !== 'utf8')
+ die("skip Not sure if UTF8 is available, cancelling the test");
+
+ mysqli_free_result($res);
+
+ if (!$res = mysqli_query($link, "SHOW CHARACTER SET LIKE 'UCS2'"))
+ die("skip Cannot run SHOW CHARACTER SET to check charsets");
+
+ if (!$tmp = mysqli_fetch_assoc($res))
+ die("skip Looks like UCS2 is not available on the server");
+
+ if (strtolower($tmp['Charset']) !== 'ucs2')
+ die("skip Not sure if UCS2 is available, cancelling the test");
+
+ mysqli_free_result($res);
+ mysqli_close($link);
+?>
+--FILE--
+<?php
+ require('table.inc');
+
+ /* some cyrillic (utf8) comes here */
+ if (!$res = mysqli_query($link, "SET NAMES UTF8")) {
+ printf("[001] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ if (!$res = mysqli_query($link, "SELECT 1 AS 'Ðндрей ХриÑтов', 2 AS 'Улф Вендел', 3 AS 'Георг Рихтер'")) {
+ printf("[002] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+ print "[003]\n";
+ var_dump(mysqli_fetch_assoc($res));
+ mysqli_free_result($res);
+
+ if (!$res = mysqli_query($link, "CREATE TABLE автори_на_mysqlnd (id integer not null auto_increment primary key, име varchar(20) character set ucs2, Ñ„Ð°Ð¼Ð¸Ð»Ð¸Ñ varchar(20) character set utf8)")) {
+ printf("[004] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+ if (!$res = mysqli_query($link, "INSERT INTO автори_на_mysqlnd (име, фамилиÑ) VALUES ('Ðндрей', 'ХриÑтов'), ('Георг', 'Рихтер'), ('Улф','Вендел')")) {
+ printf("[005] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+ if (!$res = mysqli_query($link, "INSERT INTO автори_на_mysqlnd (име, фамилиÑ) VALUES ('Andrey', 'Hristov'), ('Georg', 'Richter'), ('Ulf','Wendel')")) {
+ printf("[006] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+ if (!$res = mysqli_query($link, "INSERT INTO автори_на_mysqlnd (име, фамилиÑ) VALUES ('安德烈', 'Hristov'), ('格奥尔', 'Richter'), ('乌尔夫','Wendel')")) {
+ printf("[007] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ if (!$res = mysqli_query($link, "SELECT id, име, Ñ„Ð°Ð¼Ð¸Ð»Ð¸Ñ FROM автори_на_mysqlnd ORDER BY фамилиÑ, име")) {
+ printf("[008] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+ print "[009]\n";
+ while ($row = mysqli_fetch_assoc($res)) {
+ var_dump($row);
+ }
+ mysqli_free_result($res);
+
+ if (!$res = mysqli_query($link, "DROP TABLE автори_на_mysqlnd")) {
+ printf("[010] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ mysqli_close($link);
+ print "done!";
+?>
+--EXPECTF--
+[003]
+array(3) {
+ [%u|b%"Ðндрей ХриÑтов"]=>
+ %unicode|string%(%r[1|3]%r) "1"
+ [%u|b%"Улф Вендел"]=>
+ %unicode|string%(1) "2"
+ [%u|b%"Георг Рихтер"]=>
+ %unicode|string%(1) "3"
+}
+[009]
+array(3) {
+ [%u|b%"id"]=>
+ %unicode|string%(1) "4"
+ [%u|b%"име"]=>
+ %unicode|string%(6) "Andrey"
+ [%u|b%"фамилиÑ"]=>
+ %unicode|string%(7) "Hristov"
+}
+array(3) {
+ [%u|b%"id"]=>
+ %unicode|string%(1) "7"
+ [%u|b%"име"]=>
+ %unicode|string%(9) "安德烈"
+ [%u|b%"фамилиÑ"]=>
+ %unicode|string%(7) "Hristov"
+}
+array(3) {
+ [%u|b%"id"]=>
+ %unicode|string%(1) "5"
+ [%u|b%"име"]=>
+ %unicode|string%(5) "Georg"
+ [%u|b%"фамилиÑ"]=>
+ %unicode|string%(7) "Richter"
+}
+array(3) {
+ [%u|b%"id"]=>
+ %unicode|string%(1) "8"
+ [%u|b%"име"]=>
+ %unicode|string%(9) "格奥尔"
+ [%u|b%"фамилиÑ"]=>
+ %unicode|string%(7) "Richter"
+}
+array(3) {
+ [%u|b%"id"]=>
+ %unicode|string%(1) "6"
+ [%u|b%"име"]=>
+ %unicode|string%(3) "Ulf"
+ [%u|b%"фамилиÑ"]=>
+ %unicode|string%(6) "Wendel"
+}
+array(3) {
+ [%u|b%"id"]=>
+ %unicode|string%(1) "9"
+ [%u|b%"име"]=>
+ %unicode|string%(9) "乌尔夫"
+ [%u|b%"фамилиÑ"]=>
+ %unicode|string%(6) "Wendel"
+}
+array(3) {
+ [%u|b%"id"]=>
+ %unicode|string%(1) "3"
+ [%u|b%"име"]=>
+ %unicode|string%(6) "Улф"
+ [%u|b%"фамилиÑ"]=>
+ %unicode|string%(12) "Вендел"
+}
+array(3) {
+ [%u|b%"id"]=>
+ %unicode|string%(1) "2"
+ [%u|b%"име"]=>
+ %unicode|string%(10) "Георг"
+ [%u|b%"фамилиÑ"]=>
+ %unicode|string%(12) "Рихтер"
+}
+array(3) {
+ [%u|b%"id"]=>
+ %unicode|string%(1) "1"
+ [%u|b%"име"]=>
+ %unicode|string%(12) "Ðндрей"
+ [%u|b%"фамилиÑ"]=>
+ %unicode|string%(14) "ХриÑтов"
+}
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_fetch_assoc_oo.phpt b/ext/mysqli/tests/mysqli_fetch_assoc_oo.phpt
new file mode 100644
index 0000000..8a71fa7
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_fetch_assoc_oo.phpt
@@ -0,0 +1,86 @@
+--TEST--
+mysqli_fetch_assoc()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ // Note: no SQL type tests, internally the same function gets used as for mysqli_fetch_array() which does a lot of SQL type test
+ $mysqli = new mysqli();
+ $res = @new mysqli_result($mysqli);
+ if (!is_null($tmp = @$res->fetch_assoc()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+ if (!$mysqli = new my_mysqli($host, $user, $passwd, $db, $port, $socket))
+ printf("[002] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ if (!is_null($tmp = @$res->fetch_assoc($link)))
+ printf("[003] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$res = $mysqli->query("SELECT id, label FROM test ORDER BY id LIMIT 1")) {
+ printf("[004] [%d] %s\n", $mysqli->errno, $mysqli->error);
+ }
+
+ print "[005]\n";
+ var_dump($res->fetch_assoc());
+
+ print "[006]\n";
+ var_dump($res->fetch_assoc());
+
+ $res->free_result();
+
+ if (!$res = $mysqli->query("SELECT 1 AS a, 2 AS a, 3 AS c, 4 AS C, NULL AS d, true AS e")) {
+ printf("[007] Cannot run query, [%d] %s\n", $mysqli->errno, $mysqli->error);
+ }
+ print "[008]\n";
+ var_dump($res->fetch_assoc());
+
+ $res->free_result();
+
+ if (NULL !== ($tmp = $res->fetch_assoc()))
+ printf("[008] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_close($link);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+[005]
+array(2) {
+ [%u|b%"id"]=>
+ %unicode|string%(1) "1"
+ [%u|b%"label"]=>
+ %unicode|string%(1) "a"
+}
+[006]
+NULL
+[008]
+array(5) {
+ [%u|b%"a"]=>
+ %unicode|string%(1) "2"
+ [%u|b%"c"]=>
+ %unicode|string%(1) "3"
+ [%u|b%"C"]=>
+ %unicode|string%(1) "4"
+ [%u|b%"d"]=>
+ NULL
+ [%u|b%"e"]=>
+ %unicode|string%(1) "1"
+}
+
+Warning: mysqli_result::fetch_assoc(): Couldn't fetch mysqli_result in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_fetch_assoc_zerofill.phpt b/ext/mysqli/tests/mysqli_fetch_assoc_zerofill.phpt
new file mode 100644
index 0000000..ce7e82d
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_fetch_assoc_zerofill.phpt
@@ -0,0 +1,78 @@
+--TEST--
+mysqli_fetch_assoc() - ZEROFILL
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once('connect.inc');
+ require_once('table.inc');
+
+ function zerofill($offset, $link, $datatype, $insert = 1) {
+
+ mysqli_query($link, 'ALTER TABLE test DROP zero');
+ $sql = sprintf('ALTER TABLE test ADD zero %s UNSIGNED ZEROFILL', $datatype);
+ if (!mysqli_query($link, $sql)) {
+ // no worries - server might not support it
+ return true;
+ }
+
+ if (!mysqli_query($link, sprintf('UPDATE test SET zero = %s', $insert))) {
+ printf("[%03d] UPDATE failed, [%d] %s\n",
+ $offset, mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ if (!($res = mysqli_query($link, 'SELECT zero FROM test LIMIT 1'))) {
+ printf("[%03d] SELECT failed, [%d] %s\n",
+ $offset, mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ $row = mysqli_fetch_assoc($res);
+ $meta = mysqli_fetch_fields($res);
+ mysqli_free_result($res);
+ $meta = $meta[0];
+ $length = $meta->length;
+ if ($length > strlen($insert)) {
+
+ $expected = str_repeat('0', $length - strlen($insert));
+ $expected .= $insert;
+ if ($expected !== $row['zero']) {
+ printf("[%03d] Expecting '%s' got '%s'\n", $offset, $expected, $row['zero']);
+ return false;
+ }
+
+ } else if ($length <= 1) {
+ printf("[%03d] Length reported is too small to run test\n", $offset);
+ return false;
+ }
+
+ return true;
+ }
+
+ zerofill(2, $link, 'TINYINT');
+ zerofill(3, $link, 'SMALLINT');
+ zerofill(4, $link, 'MEDIUMINT');
+ zerofill(5, $link, 'INT');
+ zerofill(6, $link, 'INTEGER');
+ zerofill(7, $link, 'BIGINT');
+ zerofill(8, $link, 'FLOAT');
+ zerofill(9, $link, 'DOUBLE');
+ zerofill(10, $link, 'DOUBLE PRECISION');
+ zerofill(11, $link, 'DECIMAL');
+ zerofill(12, $link, 'DEC');
+
+ mysqli_close($link);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_fetch_field.phpt b/ext/mysqli/tests/mysqli_fetch_field.phpt
new file mode 100644
index 0000000..d1d358b
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_fetch_field.phpt
@@ -0,0 +1,177 @@
+--TEST--
+mysqli_fetch_field()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ // Note: no SQL type tests, internally the same function gets used as for mysqli_fetch_array() which does a lot of SQL type test
+ if (!is_null($tmp = @mysqli_fetch_field()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_fetch_field($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ $charsets = my_get_charsets($link);
+ if (!$res = mysqli_query($link, "SELECT id AS ID, label FROM test AS TEST ORDER BY id LIMIT 1")) {
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ /* ID column, binary charset */
+ $tmp = mysqli_fetch_field($res);
+ var_dump($tmp);
+
+ /* label column, result set charset */
+ $tmp = mysqli_fetch_field($res);
+ var_dump($tmp);
+ if ($tmp->charsetnr != $charsets['results']['nr']) {
+ printf("[004] Expecting charset %s/%d got %d\n",
+ $charsets['results']['charset'],
+ $charsets['results']['nr'], $tmp->charsetnr);
+ }
+ if ($tmp->length != (1 * $charsets['results']['maxlen'])) {
+ printf("[005] Expecting length %d got %d\n",
+ $charsets['results']['maxlen'],
+ $tmp->max_length);
+ }
+ if ($tmp->db != $db) {
+ printf("011] Expecting database '%s' got '%s'\n",
+ $db, $tmp->db);
+ }
+
+ var_dump(mysqli_fetch_field($res));
+
+ mysqli_free_result($res);
+
+ // Read http://bugs.php.net/bug.php?id=42344 on defaults!
+ if (NULL !== ($tmp = mysqli_fetch_field($res)))
+ printf("[006] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_query($link, "DROP TABLE IF EXISTS test"))
+ printf("[007] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, "CREATE TABLE test(id INT NOT NULL DEFAULT 1)"))
+ printf("[008] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, "INSERT INTO test(id) VALUES (2)"))
+ printf("[009] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$res = mysqli_query($link, "SELECT id as _default_test FROM test")) {
+ printf("[010] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+ var_dump(mysqli_fetch_assoc($res));
+ /* binary */
+ var_dump(mysqli_fetch_field($res));
+ mysqli_free_result($res);
+
+ mysqli_close($link);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+object(stdClass)#%d (13) {
+ [%u|b%"name"]=>
+ %unicode|string%(2) "ID"
+ [%u|b%"orgname"]=>
+ %unicode|string%(2) "id"
+ [%u|b%"table"]=>
+ %unicode|string%(4) "TEST"
+ [%u|b%"orgtable"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"def"]=>
+ %unicode|string%(0) ""
+ [%u|b%"db"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"catalog"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"max_length"]=>
+ int(1)
+ [%u|b%"length"]=>
+ int(11)
+ [%u|b%"charsetnr"]=>
+ int(63)
+ [%u|b%"flags"]=>
+ int(49155)
+ [%u|b%"type"]=>
+ int(3)
+ [%u|b%"decimals"]=>
+ int(0)
+}
+object(stdClass)#%d (13) {
+ [%u|b%"name"]=>
+ %unicode|string%(5) "label"
+ [%u|b%"orgname"]=>
+ %unicode|string%(5) "label"
+ [%u|b%"table"]=>
+ %unicode|string%(4) "TEST"
+ [%u|b%"orgtable"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"def"]=>
+ %unicode|string%(0) ""
+ [%u|b%"db"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"catalog"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"max_length"]=>
+ int(%d)
+ [%u|b%"length"]=>
+ int(%d)
+ [%u|b%"charsetnr"]=>
+ int(%d)
+ [%u|b%"flags"]=>
+ int(0)
+ [%u|b%"type"]=>
+ int(254)
+ [%u|b%"decimals"]=>
+ int(0)
+}
+bool(false)
+
+Warning: mysqli_fetch_field(): Couldn't fetch mysqli_result in %s on line %d
+array(1) {
+ [%u|b%"_default_test"]=>
+ %unicode|string%(1) "2"
+}
+object(stdClass)#%d (13) {
+ [%u|b%"name"]=>
+ %unicode|string%(13) "_default_test"
+ [%u|b%"orgname"]=>
+ %unicode|string%(2) "id"
+ [%u|b%"table"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"orgtable"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"def"]=>
+ %unicode|string%(0) ""
+ [%u|b%"db"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"catalog"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"max_length"]=>
+ int(1)
+ [%u|b%"length"]=>
+ int(11)
+ [%u|b%"charsetnr"]=>
+ int(63)
+ [%u|b%"flags"]=>
+ int(32769)
+ [%u|b%"type"]=>
+ int(3)
+ [%u|b%"decimals"]=>
+ int(0)
+}
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_fetch_field_direct.phpt b/ext/mysqli/tests/mysqli_fetch_field_direct.phpt
new file mode 100644
index 0000000..fb34e44
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_fetch_field_direct.phpt
@@ -0,0 +1,83 @@
+--TEST--
+mysqli_fetch_field_direct()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_fetch_field_direct()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_fetch_field_direct($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_fetch_field_direct($link, $link)))
+ printf("[003] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (!$res = mysqli_query($link, "SELECT id AS ID, label FROM test AS TEST ORDER BY id LIMIT 1")) {
+ printf("[004] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ var_dump(mysqli_fetch_field_direct($res, -1));
+ var_dump(mysqli_fetch_field_direct($res, 0));
+ var_dump(mysqli_fetch_field_direct($res, 2));
+
+ mysqli_free_result($res);
+
+ if (NULL !== ($tmp = mysqli_fetch_field_direct($res, 0)))
+ printf("Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Warning: mysqli_fetch_field_direct(): Field offset is invalid for resultset in %s on line %d
+bool(false)
+object(stdClass)#%d (13) {
+ [%u|b%"name"]=>
+ %unicode|string%(2) "ID"
+ [%u|b%"orgname"]=>
+ %unicode|string%(2) "id"
+ [%u|b%"table"]=>
+ %unicode|string%(4) "TEST"
+ [%u|b%"orgtable"]=>
+ %unicode|string%(4) "test"
+ [%u|b%"def"]=>
+ %unicode|string%(0) ""
+ [%u|b%"db"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"catalog"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"max_length"]=>
+ int(%d)
+ [%u|b%"length"]=>
+ int(%d)
+ [%u|b%"charsetnr"]=>
+ int(%d)
+ [%u|b%"flags"]=>
+ int(%d)
+ [%u|b%"type"]=>
+ int(%d)
+ [%u|b%"decimals"]=>
+ int(%d)
+}
+
+Warning: mysqli_fetch_field_direct(): Field offset is invalid for resultset in %s on line %d
+bool(false)
+
+Warning: mysqli_fetch_field_direct(): Couldn't fetch mysqli_result in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_fetch_field_direct_oo.phpt b/ext/mysqli/tests/mysqli_fetch_field_direct_oo.phpt
new file mode 100644
index 0000000..9d511aa
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_fetch_field_direct_oo.phpt
@@ -0,0 +1,92 @@
+--TEST--
+$res->fetch_field_direct(s)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ $mysqli = new mysqli();
+ $res = @new mysqli_result($mysqli);
+ if (!is_null($tmp = @$res->fetch_field_direct()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (!$mysqli = new my_mysqli($host, $user, $passwd, $db, $port, $socket))
+ printf("[002] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ if (!$res = $mysqli->query("SELECT id AS ID, label FROM test AS TEST ORDER BY id LIMIT 1")) {
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ if (!is_null($tmp = @$res->fetch_field_direct()))
+ printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @$res->fetch_field_direct($link)))
+ printf("[005] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @$res->fetch_field_direct($link, $link)))
+ printf("[006] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ var_dump($res->fetch_field_direct(-1));
+ var_dump($res->fetch_field_direct(0));
+ var_dump($res->fetch_field_direct(2));
+
+ $res->free_result();
+
+ if (NULL !== ($tmp = $res->fetch_field_direct(0)))
+ printf("[007] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ $mysqli->close();
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Warning: mysqli_result::fetch_field_direct(): Field offset is invalid for resultset in %s on line %d
+bool(false)
+object(stdClass)#%d (13) {
+ [%u|b%"name"]=>
+ %unicode|string%(2) "ID"
+ [%u|b%"orgname"]=>
+ %unicode|string%(2) "id"
+ [%u|b%"table"]=>
+ %unicode|string%(4) "TEST"
+ [%u|b%"orgtable"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"def"]=>
+ %unicode|string%(0) ""
+ [%u|b%"db"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"catalog"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"max_length"]=>
+ int(%d)
+ [%u|b%"length"]=>
+ int(11)
+ [%u|b%"charsetnr"]=>
+ int(%d)
+ [%u|b%"flags"]=>
+ int(%d)
+ [%u|b%"type"]=>
+ int(%d)
+ [%u|b%"decimals"]=>
+ int(%d)
+}
+
+Warning: mysqli_result::fetch_field_direct(): Field offset is invalid for resultset in %s on line %d
+bool(false)
+
+Warning: mysqli_result::fetch_field_direct(): Couldn't fetch mysqli_result in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_fetch_field_flags.phpt b/ext/mysqli/tests/mysqli_fetch_field_flags.phpt
new file mode 100644
index 0000000..8259d2f
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_fetch_field_flags.phpt
@@ -0,0 +1,243 @@
+--TEST--
+mysqli_fetch_field() - flags/field->flags
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+require_once('connect.inc');
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ die(printf("skip: [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()));
+
+if (mysqli_get_server_version($link) < 50041)
+ die("skip: Due to many MySQL Server differences, the test requires 5.0.41+");
+
+mysqli_close($link);
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+/* TODO: mysqli.c needs to export a few more constants - see all the defined() calls! */
+
+ $flags = array(
+ MYSQLI_NOT_NULL_FLAG => 'NOT_NULL',
+ MYSQLI_PRI_KEY_FLAG => 'PRI_KEY',
+ MYSQLI_UNIQUE_KEY_FLAG => 'UNIQUE_KEY',
+ MYSQLI_MULTIPLE_KEY_FLAG => 'MULTIPLE_KEY',
+ MYSQLI_BLOB_FLAG => 'BLOB',
+ MYSQLI_UNSIGNED_FLAG => 'UNSIGNED',
+ MYSQLI_ZEROFILL_FLAG => 'ZEROFILL',
+ MYSQLI_AUTO_INCREMENT_FLAG => 'AUTO_INCREMENT',
+ MYSQLI_TIMESTAMP_FLAG => 'TIMESTAMP',
+ MYSQLI_SET_FLAG => 'SET',
+ MYSQLI_NUM_FLAG => 'NUM',
+ MYSQLI_PART_KEY_FLAG => 'PART_KEY',
+ // MYSQLI_GROUP_FLAG => 'MYSQLI_GROUP_FLAG' - internal usage only
+ (defined('MYSQLI_NO_DEFAULT_VALUE_FLAG') ? MYSQLI_NO_DEFAULT_VALUE_FLAG : 4096) => 'NO_DEFAULT_VALUE',
+ (defined('MYSQLI_BINARY_FLAG') ? MYSQLI_BINARY_FLAG : 128) => 'BINARY',
+ (defined('MYSQLI_ENUM_FLAG') ? MYSQLI_ENUM_FLAG : 256) => 'ENUM',
+ // MYSQLI_BINCMP_FLAG
+ );
+
+ // 5.1.24 / 6.0.4+
+ if (defined('MYSQLI_ON_UPDATE_NOW'))
+ $flags[MYSQLI_ON_UPDATE_NOW] = 'ON_UPDATE_NOW';
+ else
+ $flags[8192] = 'ON_UPDATE_NOW';
+
+ krsort($flags);
+
+ $columns = array(
+ 'INT DEFAULT NULL' => 'NUM',
+ 'INT NOT NULL' => 'NOT_NULL NO_DEFAULT_VALUE NUM',
+ 'INT NOT NULL DEFAULT 1' => 'NOT_NULL NUM',
+ 'INT UNSIGNED DEFAULT NULL' => 'UNSIGNED NUM',
+ 'INT UNSIGNED NOT NULL' => 'NOT_NULL UNSIGNED NO_DEFAULT_VALUE NUM',
+ 'INT UNSIGNED NOT NULL DEFAULT 1' => 'NOT_NULL UNSIGNED NUM',
+ 'INT UNSIGNED ZEROFILL DEFAULT NULL' => 'UNSIGNED ZEROFILL NUM',
+ 'INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY' => 'NOT_NULL PRI_KEY UNSIGNED AUTO_INCREMENT NUM PART_KEY',
+ 'CHAR(1) DEFAULT NULL' => '',
+ 'CHAR(1) NOT NULL' => 'NOT_NULL NO_DEFAULT_VALUE',
+ 'TIMESTAMP NOT NULL' => 'NOT_NULL UNSIGNED ZEROFILL BINARY TIMESTAMP',
+ 'VARBINARY(127) DEFAULT NULL' => 'BINARY',
+ 'BLOB' => 'BLOB BINARY',
+ 'TINYBLOB' => 'BLOB BINARY',
+ 'MEDIUMBLOB' => 'BLOB BINARY',
+ 'LONGBLOB' => 'BLOB BINARY',
+ 'TEXT' => 'BLOB',
+ 'TINYTEXT' => 'BLOB',
+ 'MEDIUMTEXT' => 'BLOB',
+ 'LONGTEXT' => 'BLOB',
+ 'SET("one", "two")' => 'SET',
+ 'SET("one", "two") NOT NULL' => 'NOT_NULL SET NO_DEFAULT_VALUE',
+ 'SET("one", "two") NOT NULL DEFAULT "one"' => 'NOT_NULL SET',
+ 'ENUM("one", "two")' => 'ENUM',
+ 'ENUM("one", "two") NOT NULL' => 'NOT_NULL ENUM NO_DEFAULT_VALUE',
+ 'ENUM("one", "two") NOT NULL DEFAULT "one"' => 'NOT_NULL ENUM',
+ 'TINYINT UNIQUE' => 'UNIQUE_KEY NUM PART_KEY',
+ 'SMALLINT UNIQUE' => 'UNIQUE_KEY NUM PART_KEY',
+ 'MEDIUMINT UNIQUE DEFAULT 1' => 'UNIQUE_KEY NUM PART_KEY',
+ 'BIGINT UNSIGNED UNIQUE DEFAULT 100' => 'UNIQUE_KEY UNSIGNED NUM PART_KEY',
+ 'BIT' => 'UNSIGNED',
+ 'VARCHAR(2) NOT NULL PRIMARY KEY' => 'NOT_NULL PRI_KEY NO_DEFAULT_VALUE PART_KEY'
+ );
+
+
+
+ function checkFlags($reported_flags, $expected_flags, $flags) {
+ $found_flags = $unexpected_flags = '';
+ foreach ($flags as $code => $name) {
+ if ($reported_flags >= $code) {
+ $reported_flags -= $code;
+ $found_flags .= $name . ' ';
+ if (stristr($expected_flags, $name)) {
+ $expected_flags = trim(str_ireplace($name, '', $expected_flags));
+ } else {
+ $unexpected_flags .= $name . ' ';
+ }
+ }
+ }
+
+ return array($expected_flags, $unexpected_flags, $found_flags);
+ }
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+ if (mysqli_get_server_version($link) > 50600) {
+ $columns['TIMESTAMP NOT NULL'] = 'ON_UPDATE_NOW TIMESTAMP BINARY NOT_NULL';
+ }
+
+ foreach ($columns as $column_def => $expected_flags) {
+ if (!mysqli_query($link, 'DROP TABLE IF EXISTS test')) {
+ printf("[002] %s [%d] %s\n", $column_def,
+ mysqli_errno($link), mysqli_error($link));
+ continue;
+ }
+
+ $create = sprintf('CREATE TABLE test(id INT, col1 %s)', $column_def);
+ if (!mysqli_query($link, $create)) {
+ // Server might not support it - skip
+ continue;
+ }
+
+ if (!$res = mysqli_query($link, 'SELECT * FROM test')) {
+ printf("[003] Can't select from table, %s [%d] %s\n", $column_def,
+ mysqli_errno($link), mysqli_error($link));
+ continue;
+ }
+
+ $field = mysqli_fetch_field_direct($res, 1);
+ if (!is_object($field)) {
+ printf("[004] Fetching the meta data failed, %s [%d] %s\n", $column_def,
+ mysqli_errno($link), mysqli_error($link));
+ continue;
+ }
+ if ($field->name != 'col1') {
+ printf("[005] Field information seems wrong, %s [%d] %s\n", $column_def,
+ mysqli_errno($link), mysqli_error($link));
+ continue;
+ }
+
+ /*
+ TODO
+ Unfortunately different server versions give you slightly different
+ results.The test does not yet fully reflect all server changes/bugs etc.
+ */
+ switch ($column_def) {
+ case 'TIMESTAMP NOT NULL':
+ // http://bugs.mysql.com/bug.php?id=30081 - new flag introduced in 5.1.24/6.0.4
+ $version = mysqli_get_server_version($link);
+ if ((($version > 50122) && ($version < 60000) && ($version != 50200)) ||
+ ($version >= 60004)) {
+ // new flag ON_UPDATE_NOW_FLAG (8192)
+ $expected_flags .= ' ON_UPDATE_NOW';
+ }
+ break;
+
+ case 'INT UNSIGNED NOT NULL':
+ case 'INT NOT NULL':
+ case 'CHAR(1) NOT NULL':
+ case 'SET("one", "two") NOT NULL':
+ case 'ENUM("one", "two") NOT NULL':
+ $version = mysqli_get_server_version($link);
+ if ($version < 50000) {
+ // TODO - check exact version!
+ $expected_flags = trim(str_replace('NO_DEFAULT_VALUE', '', $expected_flags));
+ }
+ break;
+
+ case 'BIT':
+ $version = mysqli_get_server_version($link);
+ if (($version <= 50114 && $version > 50100) || ($version == 50200)) {
+ // TODO - check exact version!
+ $expected_flags = trim(str_replace('UNSIGNED', '', $expected_flags));
+ }
+
+ default:
+ break;
+ }
+
+ list($missing_flags, $unexpected_flags, $flags_found) = checkFlags($field->flags, $expected_flags, $flags);
+ if ($unexpected_flags) {
+ printf("[006] Found unexpected flags '%s' for %s, found '%s' with MySQL %s'\n",
+ $unexpected_flags, $column_def, $flags_found, mysqli_get_server_version($link));
+ }
+ if ($missing_flags) {
+ printf("[007] The flags '%s' have not been reported for %s, found '%s'\n",
+ $missing_flags, $column_def, $flags_found);
+ var_dump($create);
+ var_dump(mysqli_get_server_version($link));
+ die($missing_flags);
+ }
+
+ mysqli_free_result($res);
+ }
+
+ if (!mysqli_query($link, 'DROP TABLE IF EXISTS test')) {
+ printf("[008] %s [%d] %s\n", $column_def,
+ mysqli_errno($link), mysqli_error($link));
+ continue;
+ }
+
+ $column_def = array('col1 CHAR(1)', 'col2 CHAR(2)','INDEX idx_col1_col2(col1, col2)');
+ $expected_flags = array('col1' => 'MULTIPLE_KEY PART_KEY', 'col2' => 'PART_KEY');
+ $create = 'CREATE TABLE test(id INT, ';
+ foreach ($column_def as $k => $v) {
+ $create .= sprintf('%s, ', $v);
+ }
+ $create = sprintf('%s)', substr($create, 0, -2));
+
+ if (mysqli_query($link, $create)) {
+ if (!$res = mysqli_query($link, 'SELECT * FROM test')) {
+ printf("[009] Cannot run SELECT, [%d] %s\n",
+ mysqli_errno($link), mysqli_error($link));
+ }
+ // id column - skip it
+ $field = mysqli_fetch_field($res);
+ while ($field = mysqli_fetch_field($res)) {
+ if (!isset($expected_flags[$field->name])) {
+ printf("[010] Found unexpected field '%s'\n", $field->name);
+ continue;
+ }
+ list($missing_flags, $unexpected_flags, $flags_found) = checkFlags($field->flags, $expected_flags[$field->name], $flags);
+ if ($unexpected_flags)
+ printf("[011] Found unexpected flags '%s' for %s, found '%s'\n",
+ $unexpected_flags, $field->name, $flags_found);
+ if ($missing_flags)
+ printf("[012] The flags '%s' have not been reported for %s, found '%s'\n",
+ $missing_flags, $field->name, $flags_found);
+ }
+ }
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_fetch_field_oo.phpt b/ext/mysqli/tests/mysqli_fetch_field_oo.phpt
new file mode 100644
index 0000000..2d5ad26
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_fetch_field_oo.phpt
@@ -0,0 +1,129 @@
+--TEST--
+mysqli_fetch_field()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ // Note: no SQL type tests, internally the same function gets used as for mysqli_fetch_array() which does a lot of SQL type test
+ $mysqli = new mysqli();
+ $res = @new mysqli_result($mysqli);
+ if (!is_null($tmp = @$res->fetch_field()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+ if (!$mysqli = new mysqli($host, $user, $passwd, $db, $port, $socket))
+ printf("[002] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ if (!is_null($tmp = @$res->fetch_field($link)))
+ printf("[003] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ $charsets = my_get_charsets($link);
+
+ if (!$res = $mysqli->query("SELECT id AS ID, label FROM test AS TEST ORDER BY id LIMIT 1")) {
+ printf("[004] [%d] %s\n", $mysqli->errno, $mysqli->error);
+ }
+
+ var_dump($res->fetch_field());
+
+ $tmp = $res->fetch_field();
+ var_dump($tmp);
+ if ($tmp->charsetnr != $charsets['results']['nr']) {
+ printf("[005] Expecting charset %s/%d got %d\n",
+ $charsets['results']['charset'],
+ $charsets['results']['nr'], $tmp->charsetnr);
+ }
+ if ($tmp->length != (1 * $charsets['results']['maxlen'])) {
+ printf("[006] Expecting length %d got %d\n",
+ $charsets['results']['maxlen'],
+ $tmp->max_length);
+ }
+ if ($tmp->db != $db) {
+ printf("008] Expecting database '%s' got '%s'\n",
+ $db, $tmp->db);
+ }
+
+ var_dump($res->fetch_field());
+
+ $res->free_result();
+
+ if (NULL !== ($tmp = $res->fetch_field()))
+ printf("[007] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ $mysqli->close();
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+object(stdClass)#%d (13) {
+ [%u|b%"name"]=>
+ %unicode|string%(2) "ID"
+ [%u|b%"orgname"]=>
+ %unicode|string%(2) "id"
+ [%u|b%"table"]=>
+ %unicode|string%(4) "TEST"
+ [%u|b%"orgtable"]=>
+ %unicode|string%(4) "test"
+ [%u|b%"def"]=>
+ %unicode|string%(0) ""
+ [%u|b%"db"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"catalog"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"max_length"]=>
+ int(1)
+ [%u|b%"length"]=>
+ int(11)
+ [%u|b%"charsetnr"]=>
+ int(63)
+ [%u|b%"flags"]=>
+ int(49155)
+ [%u|b%"type"]=>
+ int(3)
+ [%u|b%"decimals"]=>
+ int(0)
+}
+object(stdClass)#%d (13) {
+ [%u|b%"name"]=>
+ %unicode|string%(5) "label"
+ [%u|b%"orgname"]=>
+ %unicode|string%(5) "label"
+ [%u|b%"table"]=>
+ %unicode|string%(4) "TEST"
+ [%u|b%"orgtable"]=>
+ %unicode|string%(4) "test"
+ [%u|b%"def"]=>
+ %unicode|string%(0) ""
+ [%u|b%"db"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"catalog"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"max_length"]=>
+ int(%d)
+ [%u|b%"length"]=>
+ int(%d)
+ [%u|b%"charsetnr"]=>
+ int(%d)
+ [%u|b%"flags"]=>
+ int(0)
+ [%u|b%"type"]=>
+ int(254)
+ [%u|b%"decimals"]=>
+ int(0)
+}
+bool(false)
+
+Warning: mysqli_result::fetch_field(): Couldn't fetch mysqli_result in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_fetch_field_types.phpt b/ext/mysqli/tests/mysqli_fetch_field_types.phpt
new file mode 100644
index 0000000..d02c02c
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_fetch_field_types.phpt
@@ -0,0 +1,126 @@
+--TEST--
+mysqli_fetch_field() - data types/field->type
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require('table.inc');
+
+ function mysqli_field_datatypes($link, $sql_type, $php_value, $php_type, $datatypes, $default_charset="latin1") {
+ if (!mysqli_query($link, "DROP TABLE IF EXISTS test")) {
+ printf("[001] %s, [%d] %s\n", $sql_type,
+ mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ $create = sprintf("CREATE TABLE test(id %s) DEFAULT CHARSET %s", $sql_type, $default_charset);
+ if (!mysqli_query($link, $create)) {
+ printf("[002] '%s' - '%s', [%d] %s\n", $sql_type, $create,
+ mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ if (is_string($php_value))
+ $sql = sprintf("INSERT INTO test(id) VALUES ('%s')", $php_value);
+ else
+ $sql = sprintf("INSERT INTO test(id) VALUES (%s)", $php_value);
+
+ if (!mysqli_query($link, $sql)) {
+ printf("[003] '%s' - '%s' - '%s', [%d] %s\n", $sql_type, $create, $sql,
+ mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ if (!$res = mysqli_query($link, 'SELECT id FROM test')) {
+ printf("[004] %s, [%d] %s\n", $sql_type,
+ mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ if (!is_object($field = mysqli_fetch_field($res))) {
+ printf("[004] %s, expecting object got %s, [%d] %s\n", $sql_type,
+ gettype($field),
+ mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ if ($field->type != $php_type) {
+ $code_name = 'unknown';
+ foreach ($datatypes as $k => $v) {
+ if ($k == $field->type) {
+ $code_name = (is_array($v)) ? $v[0] : $v;
+ break;
+ }
+ }
+ printf("[006] Expecting %d for %s got code %d for %s\n",
+ $php_type, $sql_type, $field->type, $code_name);
+ return false;
+ }
+
+ return true;
+ }
+
+ $datatypes = array(
+ MYSQLI_TYPE_TINY => array('TINYINT', 5),
+ MYSQLI_TYPE_SHORT => array('SMALLINT', 10),
+ MYSQLI_TYPE_LONG => 'MYSQLI_TYPE_LONG - TODO add testing',
+ MYSQLI_TYPE_FLOAT => array('FLOAT', '1.3'),
+ MYSQLI_TYPE_DOUBLE => array('DOUBLE', '1.4'),
+ MYSQLI_TYPE_TIMESTAMP => array('TIMESTAMP', '2007-08-20 18:34:00'),
+ MYSQLI_TYPE_LONGLONG => array('BIGINT', 100),
+ MYSQLI_TYPE_INT24 => array('MEDIUMINT', 10),
+ MYSQLI_TYPE_DATE => array('DATE', '2007-08-20'),
+ MYSQLI_TYPE_TIME => array('TIME', '18:41:38'),
+ MYSQLI_TYPE_DATETIME => array('DATETIME', '2007-08-20 18:42:01'),
+ MYSQLI_TYPE_YEAR => array('YEAR', '2007'),
+ MYSQLI_TYPE_ENUM => array('ENUM("everything", "is", "just", "wonderful")', 'is'),
+ // MYSQLI_TYPE_SET => array('SET("I", "smash", "the")', 'I,smash,the'), - string
+ // MYSQLI_TYPE_TINY_BLOB => array("TINYBLOB", "I got a tiny blog"), - blob
+ // MYSQLI_TYPE_MEDIUM_BLOB => array("MEDIUMBLOB", "No blob for masses"), - blob
+ // MYSQLI_TYPE_LONG_BLOB => array("LONGBLOB", "Small is beautiful?"), - blob
+ MYSQLI_TYPE_BLOB => array("LONGBLOB", 'MySQL does not report proper type. Use Length to distinct BLOB types'),
+ MYSQLI_TYPE_BLOB => array("MEDIUMBLOB", 'MySQL does not report proper type. Use Length to distinct BLOB types'),
+ MYSQLI_TYPE_BLOB => array("TINYBLOB", 'MySQL does not report proper type. Use Length to distinct BLOB types'),
+ MYSQLI_TYPE_BLOB => array("BLOB", 'silly'),
+ MYSQLI_TYPE_VAR_STRING => array("VARCHAR(32768)", 'varchar'),
+ MYSQLI_TYPE_STRING => 'MYSQLI_TYPE_STRING - TODO add testing',
+ MYSQLI_TYPE_STRING => array('CHAR(1)', 'a'),
+ MYSQLI_TYPE_STRING => array("SET('I', 'smash', 'the')", 'smash'),
+ MYSQLI_TYPE_NULL => 'MYSQLI_TYPE_NULL - TODO add testing',
+ MYSQLI_TYPE_NEWDATE => 'MYSQLI_TYPE_NEWDATE - TODO add testing',
+ MYSQLI_TYPE_INTERVAL => 'MYSQLI_TYPE_INTERVAL - TODO add testing',
+ MYSQLI_TYPE_GEOMETRY => 'MYSQLI_TYPE_GEOMETRY - TODO add testing',
+ );
+
+ if ($IS_MYSQLND) {
+ $version = 50007 + 1;
+ } else {
+ $version = mysqli_get_client_version();
+ }
+
+ if ($version > 50002) {
+ $datatypes[MYSQLI_TYPE_NEWDECIMAL] = array('DECIMAL', '1.1');
+ $datatypes[MYSQLI_TYPE_BIT] = array('BIT', 0);
+ } else {
+ $datatypes[MYSQLI_TYPE_DECIMAL] = array('DECIMAL', '1.1');
+ }
+
+ foreach ($datatypes as $php_type => $datatype) {
+ if (is_array($datatype))
+ mysqli_field_datatypes($link, $datatype[0], $datatype[1], $php_type, $datatypes);
+ }
+
+ mysqli_close($link);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_fetch_fields.phpt b/ext/mysqli/tests/mysqli_fetch_fields.phpt
new file mode 100644
index 0000000..479c71c
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_fetch_fields.phpt
@@ -0,0 +1,121 @@
+--TEST--
+mysqli_fetch_fields()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ // Note: no SQL type tests, internally the same function gets used as for mysqli_fetch_array() which does a lot of SQL type test
+ if (!is_null($tmp = @mysqli_fetch_fields()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_fetch_fields($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+ $charsets = my_get_charsets($link);
+
+ if (!$res = mysqli_query($link, "SELECT id AS ID, label FROM test AS TEST ORDER BY id LIMIT 1")) {
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ $fields = mysqli_fetch_fields($res);
+ foreach ($fields as $k => $field) {
+ var_dump($field);
+ switch ($k) {
+ case 1:
+ /* label column, result set charset */
+ if ($field->charsetnr != $charsets['results']['nr']) {
+ printf("[004] Expecting charset %s/%d got %d\n",
+ $charsets['results']['charset'],
+ $charsets['results']['nr'], $field->charsetnr);
+ }
+ if ($field->length != (1 * $charsets['results']['maxlen'])) {
+ printf("[005] Expecting length %d got %d\n",
+ $charsets['results']['maxlen'],
+ $field->max_length);
+ }
+ break;
+ }
+ }
+
+ mysqli_free_result($res);
+
+ if (NULL !== ($tmp = mysqli_fetch_fields($res)))
+ printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+object(stdClass)#%d (13) {
+ [%u|b%"name"]=>
+ %unicode|string%(2) "ID"
+ [%u|b%"orgname"]=>
+ %unicode|string%(2) "id"
+ [%u|b%"table"]=>
+ %unicode|string%(4) "TEST"
+ [%u|b%"orgtable"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"def"]=>
+ %unicode|string%(0) ""
+ [%u|b%"db"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"catalog"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"max_length"]=>
+ int(1)
+ [%u|b%"length"]=>
+ int(11)
+ [%u|b%"charsetnr"]=>
+ int(63)
+ [%u|b%"flags"]=>
+ int(49155)
+ [%u|b%"type"]=>
+ int(3)
+ [%u|b%"decimals"]=>
+ int(0)
+}
+object(stdClass)#%d (13) {
+ [%u|b%"name"]=>
+ %unicode|string%(5) "label"
+ [%u|b%"orgname"]=>
+ %unicode|string%(5) "label"
+ [%u|b%"table"]=>
+ %unicode|string%(4) "TEST"
+ [%u|b%"orgtable"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"def"]=>
+ %unicode|string%(0) ""
+ [%u|b%"db"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"catalog"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"max_length"]=>
+ int(1)
+ [%u|b%"length"]=>
+ int(%d)
+ [%u|b%"charsetnr"]=>
+ int(%d)
+ [%u|b%"flags"]=>
+ int(0)
+ [%u|b%"type"]=>
+ int(254)
+ [%u|b%"decimals"]=>
+ int(0)
+}
+
+Warning: mysqli_fetch_fields(): Couldn't fetch mysqli_result in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_fetch_lengths.phpt b/ext/mysqli/tests/mysqli_fetch_lengths.phpt
new file mode 100644
index 0000000..1abc611
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_fetch_lengths.phpt
@@ -0,0 +1,55 @@
+--TEST--
+mysqli_fetch_lengths()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ if (!$mysqli = new mysqli($host, $user, $passwd, $db, $port, $socket))
+ printf("[001] Cannot connect\n");
+
+ if (!is_null($tmp = @mysqli_fetch_lengths()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_fetch_lengths($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+ if (!$res = mysqli_query($link, "SELECT id, label FROM test ORDER BY id LIMIT 1")) {
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ var_dump(mysqli_fetch_lengths($res));
+ while ($row = mysqli_fetch_assoc($res))
+ var_dump(mysqli_fetch_lengths($res));
+ var_dump(mysqli_fetch_lengths($res));
+
+ mysqli_free_result($res);
+
+ var_dump(mysqli_fetch_lengths($res));
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+bool(false)
+array(2) {
+ [0]=>
+ int(1)
+ [1]=>
+ int(1)
+}
+bool(false)
+
+Warning: mysqli_fetch_lengths(): Couldn't fetch mysqli_result in %s on line %d
+NULL
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_fetch_lengths_oo.phpt b/ext/mysqli/tests/mysqli_fetch_lengths_oo.phpt
new file mode 100644
index 0000000..7523621
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_fetch_lengths_oo.phpt
@@ -0,0 +1,50 @@
+--TEST--
+mysqli_result->lengths
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ if (!$mysqli = new my_mysqli($host, $user, $passwd, $db, $port, $socket))
+ printf("[001] Cannot connect\n");
+
+ require('table.inc');
+ if (!$res = $mysqli->query("SELECT id, label FROM test ORDER BY id LIMIT 1")) {
+ printf("[002] [%d] %s\n", $mysqli->errno, $mysqli->error);
+ }
+
+ var_dump($res->lengths);
+ while ($row = $res->fetch_assoc())
+ var_dump($res->lengths);
+ var_dump($res->lengths);
+
+ $res->free_result();
+ var_dump($res->lengths);
+ $mysqli->close();
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+NULL
+array(2) {
+ [0]=>
+ int(1)
+ [1]=>
+ int(1)
+}
+NULL
+
+Warning: main(): Property access is not allowed yet in %s on line %d
+NULL
+done!
diff --git a/ext/mysqli/tests/mysqli_fetch_object.phpt b/ext/mysqli/tests/mysqli_fetch_object.phpt
new file mode 100644
index 0000000..c70871e
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_fetch_object.phpt
@@ -0,0 +1,156 @@
+--TEST--
+mysqli_fetch_object()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ include_once("connect.inc");
+
+ set_error_handler('handle_catchable_fatal');
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_fetch_object()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_fetch_object($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+ if (!$res = mysqli_query($link, "SELECT id AS ID, label FROM test AS TEST ORDER BY id LIMIT 5")) {
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ $obj = mysqli_fetch_object($res);
+ if (($obj->ID !== "1") || ($obj->label !== "a") || (get_class($obj) != 'stdClass')) {
+ printf("[004] Object seems wrong. [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ var_dump($obj);
+ }
+
+ class mysqli_fetch_object_test {
+
+ public $a = null;
+ public $b = null;
+
+ public function toString() {
+ var_dump($this);
+ }
+ }
+
+ $obj = mysqli_fetch_object($res, 'mysqli_fetch_object_test');
+ if (($obj->ID !== "2") || ($obj->label !== "b") || ($obj->a !== NULL) || ($obj->b !== NULL) || (get_class($obj) != 'mysqli_fetch_object_test')) {
+ printf("[005] Object seems wrong. [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ var_dump($obj);
+ }
+
+
+
+ class mysqli_fetch_object_construct extends mysqli_fetch_object_test {
+
+ public function __construct($a, $b) {
+ $this->a = $a;
+ $this->b = $b;
+ }
+
+ }
+
+ $obj = mysqli_fetch_object($res, 'mysqli_fetch_object_construct', array());
+
+ if (($obj->ID !== "3") || ($obj->label !== "c") || ($obj->a !== NULL) || ($obj->b !== NULL) || (get_class($obj) != 'mysqli_fetch_object_construct')) {
+ printf("[006] Object seems wrong. [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ var_dump($obj);
+ }
+
+ $obj = mysqli_fetch_object($res, 'mysqli_fetch_object_construct', array('a'));
+ if (($obj->ID !== "4") || ($obj->label !== "d") || ($obj->a !== 'a') || ($obj->b !== NULL) || (get_class($obj) != 'mysqli_fetch_object_construct')) {
+ printf("[007] Object seems wrong. [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ var_dump($obj);
+ }
+
+ $obj = mysqli_fetch_object($res, 'mysqli_fetch_object_construct', array('a', 'b'));
+ if (($obj->ID !== "5") || ($obj->label !== "e") || ($obj->a !== 'a') || ($obj->b !== 'b') || (get_class($obj) != 'mysqli_fetch_object_construct')) {
+ printf("[008] Object seems wrong. [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ var_dump($obj);
+ }
+
+ var_dump(mysqli_fetch_object($res, 'mysqli_fetch_object_construct', array('a', 'b', 'c')));
+ var_dump(mysqli_fetch_object($res));
+
+ mysqli_free_result($res);
+
+ if (!$res = mysqli_query($link, "SELECT id AS ID, label FROM test AS TEST")) {
+ printf("[009] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ mysqli_free_result($res);
+ var_dump(mysqli_fetch_object($res));
+
+ if (!$res = mysqli_query($link, "SELECT id AS ID, label FROM test AS TEST ORDER BY id LIMIT 5"))
+ printf("[010] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ /*
+ TODO
+ I'm using the procedural interface, this should not throw an exception.
+ Also, I did not ask to get exceptions using the mysqli_options()
+ */
+ try {
+ if (false !== ($obj = @mysqli_fetch_object($res, 'mysqli_fetch_object_construct', 'a')))
+ printf("[011] Should have failed\n");
+ } catch (Exception $e) {
+ printf("%s\n", $e->getMessage());
+ }
+
+ mysqli_free_result($res);
+
+ if (!$res = mysqli_query($link, "SELECT id AS ID, label FROM test AS TEST ORDER BY id LIMIT 5"))
+ printf("[012] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ class mysqli_fetch_object_private_constructor extends mysqli_fetch_object_test {
+
+ private function __construct($a, $b) {
+ $this->a = $a;
+ $this->b = $b;
+ }
+ }
+ /*
+ TODO
+ I think we should bail out here. The following line will give a Fatal error: Call to private ... from invalid context
+ var_dump($obj = new mysqli_fetch_object_private_constructor(1, 2));
+ This does not fail.
+ */
+ $obj = mysqli_fetch_object($res, 'mysqli_fetch_object_private_constructor', array('a', 'b'));
+ mysqli_free_result($res);
+
+ // Fatal error, script execution will end
+ var_dump(mysqli_fetch_object($res, 'this_class_does_not_exist'));
+
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+[E_WARNING] mysqli_fetch_object() expects at least 1 parameter, 0 given in %s on line %d
+[E_WARNING] mysqli_fetch_object() expects parameter 1 to be mysqli_result, null given in %s on line %d
+[E_WARNING] Missing argument 1 for mysqli_fetch_object_construct::__construct() in %s on line %d
+[E_WARNING] Missing argument 2 for mysqli_fetch_object_construct::__construct() in %s on line %d
+[E_NOTICE] Undefined variable: a in %s on line %d
+[E_NOTICE] Undefined variable: b in %s on line %d
+[E_WARNING] Missing argument 2 for mysqli_fetch_object_construct::__construct() in %s on line %d
+[E_NOTICE] Undefined variable: b in %s on line %d
+NULL
+NULL
+[E_WARNING] mysqli_fetch_object(): Couldn't fetch mysqli_result in %s on line %d
+NULL
+[E_RECOVERABLE_ERROR] Argument 3 passed to mysqli_fetch_object() must be of the type array, string given in %s on line %d
+Parameter ctor_params must be an array
+
+Fatal error: Class 'this_class_does_not_exist' not found in %s on line %d \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_fetch_object_no_constructor.phpt b/ext/mysqli/tests/mysqli_fetch_object_no_constructor.phpt
new file mode 100644
index 0000000..2fa80cf
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_fetch_object_no_constructor.phpt
@@ -0,0 +1,65 @@
+--TEST--
+mysqli_fetch_object() - calling constructor on class wo constructor
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ require('table.inc');
+ if (!$res = mysqli_query($link, "SELECT id AS ID, label FROM test AS TEST ORDER BY id LIMIT 5")) {
+ printf("[001] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ class mysqli_fetch_object_test {
+
+ public $a = null;
+ public $b = null;
+
+ public function toString() {
+ var_dump($this);
+ }
+ }
+
+ printf("No exception with PHP:\n");
+ var_dump($obj = new mysqli_fetch_object_test(1, 2));
+
+ printf("\nException with mysqli. Note that at all other places we throws errors but no exceptions unless the error mode has been changed:\n");
+ try {
+ var_dump($obj = mysqli_fetch_object($res, 'mysqli_fetch_object_test', array(1, 2)));
+ } catch (Exception $e) {
+ printf("Exception: %s\n", $e->getMessage());
+ }
+
+ printf("\nFatal error with PHP (but no exception!):\n");
+ var_dump($obj->mysqli_fetch_object_test(1, 2));
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+No exception with PHP:
+object(mysqli_fetch_object_test)#%d (%d) {
+ [%u|b%"a"]=>
+ NULL
+ [%u|b%"b"]=>
+ NULL
+}
+
+Exception with mysqli. Note that at all other places we throws errors but no exceptions unless the error mode has been changed:
+Exception: Class mysqli_fetch_object_test does not have a constructor hence you cannot use ctor_params
+
+Fatal error with PHP (but no exception!):
+
+Fatal error: Call to undefined method mysqli_fetch_object_test::mysqli_fetch_object_test() in %s on line %d
diff --git a/ext/mysqli/tests/mysqli_fetch_object_no_object.phpt b/ext/mysqli/tests/mysqli_fetch_object_no_object.phpt
new file mode 100644
index 0000000..c8e2b85
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_fetch_object_no_object.phpt
@@ -0,0 +1,27 @@
+--TEST--
+mysqli_fetch_object()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require('table.inc');
+ if (!$res = mysqli_query($link, "SELECT id AS ID, label FROM test AS TEST ORDER BY id LIMIT 5")) {
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ $obj = mysqli_fetch_object($res);
+ var_dump(gettype($obj));
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+%s(6) "object"
+done!
diff --git a/ext/mysqli/tests/mysqli_fetch_object_oo.phpt b/ext/mysqli/tests/mysqli_fetch_object_oo.phpt
new file mode 100644
index 0000000..1d62c6d
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_fetch_object_oo.phpt
@@ -0,0 +1,134 @@
+--TEST--
+mysqli_fetch_object()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+ set_error_handler('handle_catchable_fatal');
+
+ $tmp = NULL;
+ $link = NULL;
+
+ $mysqli = new mysqli();
+ $res = @new mysqli_result($mysqli);
+ if (!is_null($tmp = @$res->fetch_object()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+ if (!$mysqli = new my_mysqli($host, $user, $passwd, $db, $port, $socket))
+ printf("[002] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ if (!$res = $mysqli->query("SELECT id AS ID, label FROM test AS TEST ORDER BY id LIMIT 5")) {
+ printf("[003] [%d] %s\n", $mysqli->errno, $mysqli->error);
+ }
+
+ if (!is_null($tmp = @$res->fetch_object($link)))
+ printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @$res->fetch_object($link, $link)))
+ printf("[005] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @$res->fetch_object($link, $link, $link)))
+ printf("[006] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ $obj = mysqli_fetch_object($res);
+ if (($obj->ID !== "1") || ($obj->label !== "a") || (get_class($obj) != 'stdClass')) {
+ printf("[007] Object seems wrong. [%d] %s\n", $mysqli->errno, $mysqli->error);
+ var_dump($obj);
+ }
+
+ class mysqli_fetch_object_test {
+
+ public $a = null;
+ public $b = null;
+
+ public function toString() {
+ var_dump($this);
+ }
+ }
+
+ $obj = $res->fetch_object('mysqli_fetch_object_test');
+ if (($obj->ID !== "2") || ($obj->label !== "b") || ($obj->a !== NULL) || ($obj->b !== NULL) || (get_class($obj) != 'mysqli_fetch_object_test')) {
+ printf("[008] Object seems wrong. [%d] %s\n", $mysqli->errno, $mysqli->error);
+ var_dump($obj);
+ }
+
+ class mysqli_fetch_object_construct extends mysqli_fetch_object_test {
+
+ public function __construct($a, $b) {
+ $this->a = $a;
+ $this->b = $b;
+ }
+
+ }
+
+ $obj = $res->fetch_object('mysqli_fetch_object_construct', null);
+
+ if (($obj->ID !== "3") || ($obj->label !== "c") || ($obj->a !== NULL) || ($obj->b !== NULL) || (get_class($obj) != 'mysqli_fetch_object_construct')) {
+ printf("[009] Object seems wrong. [%d] %s\n", $mysqli->errno, $mysqli->error);
+ var_dump($obj);
+ }
+
+ $obj = $res->fetch_object('mysqli_fetch_object_construct', array('a'));
+ if (($obj->ID !== "4") || ($obj->label !== "d") || ($obj->a !== 'a') || ($obj->b !== NULL) || (get_class($obj) != 'mysqli_fetch_object_construct')) {
+ printf("[010] Object seems wrong. [%d] %s\n", $mysqli->errno, $mysqli->error);
+ var_dump($obj);
+ }
+
+ $obj = $res->fetch_object('mysqli_fetch_object_construct', array('a', 'b'));
+ if (($obj->ID !== "5") || ($obj->label !== "e") || ($obj->a !== 'a') || ($obj->b !== 'b') || (get_class($obj) != 'mysqli_fetch_object_construct')) {
+ printf("[011] Object seems wrong. [%d] %s\n", $mysqli->errno, $mysqli->error);
+ var_dump($obj);
+ }
+
+ var_dump($res->fetch_object('mysqli_fetch_object_construct', array('a', 'b', 'c')));
+ var_dump(mysqli_fetch_object($res));
+
+ mysqli_free_result($res);
+
+ if (!$res = mysqli_query($link, "SELECT id AS ID, label FROM test AS TEST")) {
+ printf("[012] [%d] %s\n", $mysqli->errno, $mysqli->error);
+ }
+
+ mysqli_free_result($res);
+
+ var_dump(mysqli_fetch_object($res));
+
+ // Fatal error, script execution will end
+ var_dump($res->fetch_object('this_class_does_not_exist'));
+
+ $mysqli->close();
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+[E_WARNING] mysqli_result::__construct(): invalid object or resource mysql%s
+%s on line %d
+[E_WARNING] mysqli_result::fetch_object(): Couldn't fetch mysqli_result in %s on line %d
+[E_WARNING] mysqli_result::fetch_object() expects parameter 1 to be string, object given in %s on line %d
+[E_RECOVERABLE_ERROR] Argument 2 passed to mysqli_result::fetch_object() must be of the type array, object given in %s on line %d
+[E_WARNING] mysqli_result::fetch_object() expects parameter 1 to be string, object given in %s on line %d
+[E_RECOVERABLE_ERROR] Argument 2 passed to mysqli_result::fetch_object() must be of the type array, object given in %s on line %d
+[E_WARNING] mysqli_result::fetch_object() expects at most 2 parameters, 3 given in %s on line %d
+[E_RECOVERABLE_ERROR] Argument 2 passed to mysqli_result::fetch_object() must be of the type array, null given in %s on line %d
+[E_WARNING] Missing argument 1 for mysqli_fetch_object_construct::__construct() in %s on line %d
+[E_WARNING] Missing argument 2 for mysqli_fetch_object_construct::__construct() in %s on line %d
+[E_NOTICE] Undefined variable: a in %s on line %d
+[E_NOTICE] Undefined variable: b in %s on line %d
+[E_WARNING] Missing argument 2 for mysqli_fetch_object_construct::__construct() in %s on line %d
+[E_NOTICE] Undefined variable: b in %s on line %d
+NULL
+NULL
+[E_WARNING] mysqli_fetch_object(): Couldn't fetch mysqli_result in %s on line %d
+NULL
+
+Fatal error: Class 'this_class_does_not_exist' not found in %s on line %d \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_fetch_row.phpt b/ext/mysqli/tests/mysqli_fetch_row.phpt
new file mode 100644
index 0000000..e0359e0
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_fetch_row.phpt
@@ -0,0 +1,59 @@
+--TEST--
+mysqli_fetch_row()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_fetch_row()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_fetch_row($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+ if (!$res = mysqli_query($link, "SELECT id, label, id AS _id FROM test ORDER BY id LIMIT 1")) {
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ print "[004]\n";
+ var_dump(mysqli_fetch_row($res));
+
+ print "[005]\n";
+ var_dump(mysqli_fetch_row($res));
+
+ mysqli_free_result($res);
+
+ var_dump(mysqli_fetch_row($res));
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+[004]
+array(3) {
+ [0]=>
+ %unicode|string%(1) "1"
+ [1]=>
+ %unicode|string%(1) "a"
+ [2]=>
+ %unicode|string%(1) "1"
+}
+[005]
+NULL
+
+Warning: mysqli_fetch_row(): Couldn't fetch mysqli_result in %s on line %d
+NULL
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_field_count.phpt b/ext/mysqli/tests/mysqli_field_count.phpt
new file mode 100644
index 0000000..9a778c9
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_field_count.phpt
@@ -0,0 +1,63 @@
+--TEST--
+mysqli_field_count()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_field_count()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_field_count($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ var_dump(mysqli_field_count($link));
+
+ if (!$res = mysqli_query($link, "SELECT * FROM test ORDER BY id LIMIT 1")) {
+ printf("[004] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ var_dump(mysqli_field_count($link));
+
+ mysqli_free_result($res);
+
+ if (!mysqli_query($link, "INSERT INTO test(id, label) VALUES (100, 'x')"))
+ printf("[005] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ var_dump($link->field_count);
+ var_dump(mysqli_field_count($link));
+
+ if (!$res = mysqli_query($link, "SELECT NULL as _null, '' AS '', 'three' AS 'drei'"))
+ printf("[006] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ var_dump(mysqli_field_count($link));
+ mysqli_free_result($res);
+
+ mysqli_close($link);
+
+ var_dump(mysqli_field_count($link));
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+int(0)
+int(2)
+int(0)
+int(0)
+int(3)
+
+Warning: mysqli_field_count(): Couldn't fetch mysqli in %s on line %d
+NULL
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_field_seek.phpt b/ext/mysqli/tests/mysqli_field_seek.phpt
new file mode 100644
index 0000000..a747bdf
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_field_seek.phpt
@@ -0,0 +1,251 @@
+--TEST--
+mysqli_field_seek()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ function mysqli_field_seek_flags($flags) {
+
+ $ret = '';
+
+ if ($flags & MYSQLI_NOT_NULL_FLAG)
+ $ret .= 'MYSQLI_NOT_NULL_FLAG ';
+
+ if ($flags & MYSQLI_PRI_KEY_FLAG)
+ $ret .= 'MYSQLI_PRI_KEY_FLAG ';
+
+ if ($flags & MYSQLI_UNIQUE_KEY_FLAG)
+ $ret .= 'MYSQLI_UNIQUE_KEY_FLAG ';
+
+ if ($flags & MYSQLI_MULTIPLE_KEY_FLAG)
+ $ret .= 'MYSQLI_MULTIPLE_KEY_FLAG ';
+
+ if ($flags & MYSQLI_BLOB_FLAG)
+ $ret .= 'MYSQLI_BLOB_FLAG ';
+
+ if ($flags & MYSQLI_UNSIGNED_FLAG)
+ $ret .= 'MYSQLI_UNSIGNED_FLAG ';
+
+ if ($flags & MYSQLI_ZEROFILL_FLAG)
+ $ret .= 'MYSQLI_ZEROFILL_FLAG ';
+
+ if ($flags & MYSQLI_AUTO_INCREMENT_FLAG)
+ $ret .= 'MYSQLI_AUTO_INCREMENT_FLAG ';
+
+ if ($flags & MYSQLI_TIMESTAMP_FLAG)
+ $ret .= 'MYSQLI_TIMESTAMP_FLAG ';
+
+ if ($flags & MYSQLI_SET_FLAG)
+ $ret .= 'MYSQLI_SET_FLAG ';
+
+ if ($flags & MYSQLI_NUM_FLAG)
+ $ret .= 'MYSQLI_NUM_FLAG ';
+
+ if ($flags & MYSQLI_PART_KEY_FLAG)
+ $ret .= 'MYSQLI_PART_KEY_FLAG ';
+
+ if ($flags & MYSQLI_GROUP_FLAG)
+ $ret .= 'MYSQLI_GROUP_FLAG ';
+
+ return $ret;
+ }
+
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_field_seek()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_field_seek($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+ $charsets = my_get_charsets($link);
+
+ if (!$res = mysqli_query($link, "SELECT id, label FROM test ORDER BY id LIMIT 1", MYSQLI_USE_RESULT)) {
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ var_dump(mysqli_field_seek($res, -1));
+ var_dump(mysqli_fetch_field($res));
+ var_dump(mysqli_field_seek($res, 0));
+ var_dump(mysqli_fetch_field($res));
+ var_dump(mysqli_field_seek($res, 1));
+
+ $field = mysqli_fetch_field($res);
+ var_dump($field);
+ /* label column, result set charset */
+ if ($field->charsetnr != $charsets['results']['nr']) {
+ printf("[004] Expecting charset %s/%d got %d\n",
+ $charsets['results']['charset'],
+ $charsets['results']['nr'], $field->charsetnr);
+ }
+ if ($field->length != (1 * $charsets['results']['maxlen'])) {
+ printf("[005] Expecting length %d got %d\n",
+ $charsets['results']['maxlen'],
+ $field->max_length);
+ }
+
+ var_dump(mysqli_field_tell($res));
+ var_dump(mysqli_field_seek($res, 2));
+ var_dump(mysqli_fetch_field($res));
+ var_dump(mysqli_field_seek($res, PHP_INT_MAX + 1));
+
+ if (!is_null($tmp = @mysqli_field_seek($res, 0, "too many")))
+ printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_free_result($res);
+
+ if (!$res = mysqli_query($link, "SELECT NULL as _null", MYSQLI_STORE_RESULT)) {
+ printf("[005] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+ var_dump(mysqli_field_seek($res, 0));
+ var_dump(mysqli_fetch_field($res));
+
+ mysqli_free_result($res);
+
+ var_dump(mysqli_field_seek($res, 0));
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Warning: mysqli_field_seek(): Invalid field offset in %s on line %d
+bool(false)
+object(stdClass)#%d (13) {
+ [%u|b%"name"]=>
+ %unicode|string%(2) "id"
+ [%u|b%"orgname"]=>
+ %unicode|string%(2) "id"
+ [%u|b%"table"]=>
+ %unicode|string%(4) "test"
+ [%u|b%"orgtable"]=>
+ %unicode|string%(4) "test"
+ [%u|b%"def"]=>
+ %unicode|string%(0) ""
+ [%u|b%"db"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"catalog"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"max_length"]=>
+ int(0)
+ [%u|b%"length"]=>
+ int(11)
+ [%u|b%"charsetnr"]=>
+ int(63)
+ [%u|b%"flags"]=>
+ int(49155)
+ [%u|b%"type"]=>
+ int(3)
+ [%u|b%"decimals"]=>
+ int(0)
+}
+bool(true)
+object(stdClass)#%d (13) {
+ [%u|b%"name"]=>
+ %unicode|string%(2) "id"
+ [%u|b%"orgname"]=>
+ %unicode|string%(2) "id"
+ [%u|b%"table"]=>
+ %unicode|string%(4) "test"
+ [%u|b%"orgtable"]=>
+ %unicode|string%(4) "test"
+ [%u|b%"def"]=>
+ %unicode|string%(0) ""
+ [%u|b%"db"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"catalog"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"max_length"]=>
+ int(0)
+ [%u|b%"length"]=>
+ int(11)
+ [%u|b%"charsetnr"]=>
+ int(63)
+ [%u|b%"flags"]=>
+ int(49155)
+ [%u|b%"type"]=>
+ int(3)
+ [%u|b%"decimals"]=>
+ int(0)
+}
+bool(true)
+object(stdClass)#%d (13) {
+ [%u|b%"name"]=>
+ %unicode|string%(5) "label"
+ [%u|b%"orgname"]=>
+ %unicode|string%(5) "label"
+ [%u|b%"table"]=>
+ %unicode|string%(4) "test"
+ [%u|b%"orgtable"]=>
+ %unicode|string%(4) "test"
+ [%u|b%"def"]=>
+ %unicode|string%(0) ""
+ [%u|b%"db"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"catalog"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"max_length"]=>
+ int(%d)
+ [%u|b%"length"]=>
+ int(%d)
+ [%u|b%"charsetnr"]=>
+ int(%d)
+ [%u|b%"flags"]=>
+ int(0)
+ [%u|b%"type"]=>
+ int(254)
+ [%u|b%"decimals"]=>
+ int(0)
+}
+int(2)
+
+Warning: mysqli_field_seek(): Invalid field offset in %s on line %d
+bool(false)
+bool(false)
+
+Warning: mysqli_field_seek(): Invalid field offset in %s on line %d
+bool(false)
+bool(true)
+object(stdClass)#3 (13) {
+ [%u|b%"name"]=>
+ %unicode|string%(5) "_null"
+ [%u|b%"orgname"]=>
+ %unicode|string%(0) ""
+ [%u|b%"table"]=>
+ %unicode|string%(0) ""
+ [%u|b%"orgtable"]=>
+ %unicode|string%(0) ""
+ [%u|b%"def"]=>
+ %unicode|string%(0) ""
+ [%u|b%"db"]=>
+ %unicode|string%(0) ""
+ [%u|b%"catalog"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"max_length"]=>
+ int(0)
+ [%u|b%"length"]=>
+ int(0)
+ [%u|b%"charsetnr"]=>
+ int(63)
+ [%u|b%"flags"]=>
+ int(32896)
+ [%u|b%"type"]=>
+ int(6)
+ [%u|b%"decimals"]=>
+ int(0)
+}
+
+Warning: mysqli_field_seek(): Couldn't fetch mysqli_result in %s on line %d
+NULL
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_field_tell.phpt b/ext/mysqli/tests/mysqli_field_tell.phpt
new file mode 100644
index 0000000..cac2001
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_field_tell.phpt
@@ -0,0 +1,110 @@
+--TEST--
+mysqli_field_tell()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_field_tell()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_field_tell($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+ if (!$res = mysqli_query($link, "SELECT id FROM test ORDER BY id LIMIT 1", MYSQLI_USE_RESULT)) {
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ var_dump(mysqli_field_tell($res));
+ var_dump(mysqli_field_seek(1));
+ var_dump(mysqli_field_tell($res));
+ var_dump(mysqli_fetch_field($res));
+ var_dump(mysqli_fetch_field($res));
+ var_dump(mysqli_field_tell($res));
+
+ if (!is_null($tmp = @mysqli_field_tell($res, 'too many arguments')))
+ printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+
+ var_dump(mysqli_field_seek($res, 2));
+ var_dump(mysqli_field_tell($res));
+
+ var_dump(mysqli_field_seek($res, -1));
+ var_dump(mysqli_field_tell($res));
+
+ var_dump(mysqli_field_seek($res, 0));
+ var_dump(mysqli_field_tell($res));
+
+
+
+ mysqli_free_result($res);
+
+ var_dump(mysqli_field_tell($res));
+
+ mysqli_close($link);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+int(0)
+
+Warning: mysqli_field_seek() expects exactly 2 parameters, 1 given in %s on line %d
+NULL
+int(0)
+object(stdClass)#%d (13) {
+ [%u|b%"name"]=>
+ %unicode|string%(2) "id"
+ [%u|b%"orgname"]=>
+ %unicode|string%(2) "id"
+ [%u|b%"table"]=>
+ %unicode|string%(4) "test"
+ [%u|b%"orgtable"]=>
+ %unicode|string%(4) "test"
+ [%u|b%"def"]=>
+ %unicode|string%(0) ""
+ [%u|b%"db"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"catalog"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"max_length"]=>
+ int(0)
+ [%u|b%"length"]=>
+ int(11)
+ [%u|b%"charsetnr"]=>
+ int(63)
+ [%u|b%"flags"]=>
+ int(49155)
+ [%u|b%"type"]=>
+ int(3)
+ [%u|b%"decimals"]=>
+ int(0)
+}
+bool(false)
+int(1)
+
+Warning: mysqli_field_seek(): Invalid field offset in %s on line %d
+bool(false)
+int(1)
+
+Warning: mysqli_field_seek(): Invalid field offset in %s on line %d
+bool(false)
+int(1)
+bool(true)
+int(0)
+
+Warning: mysqli_field_tell(): Couldn't fetch mysqli_result in %s on line %d
+NULL
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_fork.phpt b/ext/mysqli/tests/mysqli_fork.phpt
new file mode 100644
index 0000000..f5a0b7b
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_fork.phpt
@@ -0,0 +1,252 @@
+--TEST--
+Forking a child and using the same connection.
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+if (!function_exists('pcntl_fork'))
+ die("skip Process Control Functions not available");
+
+if (!function_exists('posix_getpid'))
+ die("skip POSIX functions not available");
+
+require_once('connect.inc');
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ die(sprintf("Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error()));
+
+if (!have_innodb($link))
+ die(sprintf("Needs InnoDB support, [%d] %s", $link->errno, $link->error));
+?>
+--FILE--
+<?php
+ require_once("table.inc");
+
+ $res = mysqli_query($link, "SELECT 'dumped by the parent' AS message");
+ $pid = pcntl_fork();
+ switch ($pid) {
+ case -1:
+ printf("[001] Cannot fork child");
+ break;
+
+ case 0:
+ /* child */
+ exit(0);
+ break;
+
+ default:
+ /* parent */
+ $status = null;
+ $wait_id = pcntl_waitpid($pid, $status);
+ if (pcntl_wifexited($status) && (0 != ($tmp = pcntl_wexitstatus($status)))) {
+ printf("Exit code: %s\n", (pcntl_wifexited($status)) ? pcntl_wexitstatus($status) : 'n/a');
+ printf("Signal: %s\n", (pcntl_wifsignaled($status)) ? pcntl_wtermsig($status) : 'n/a');
+ printf("Stopped: %d\n", (pcntl_wifstopped($status)) ? pcntl_wstopsig($status) : 'n/a');
+ }
+ var_dump(mysqli_fetch_assoc($res));
+ mysqli_free_result($res);
+ break;
+ }
+
+ if (@mysqli_query($link, "SELECT id FROM test WHERE id = 1"))
+ printf("[003] Expecting error and closed connection, child exit should have closed connection\n");
+ else if ((($errno = mysqli_errno($link)) == 0) || ('' == ($error = mysqli_error($link))))
+ printf("[004] Expecting error string and error code from MySQL, got errno = %s/%s, error = %s/%s\n",
+ gettype($errno), $errno, gettype($error), $error);
+
+ mysqli_close($link);
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[005] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ /* non trivial tests require a message list for parent-child communication */
+ if (!mysqli_query($link, "DROP TABLE IF EXISTS messages"))
+ printf("[006] [%d] %s\n", mysqli_error($link), mysqli_errno($link));
+
+ if (!mysqli_query($link, "CREATE TABLE messages(
+ msg_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
+ msg_time TIMESTAMP,
+ pid INT NOT NULL,
+ sender ENUM('child', 'parent') NOT NULL,
+ msg TEXT) ENGINE = InnoDB"))
+ printf("[007] [%d] %s\n", mysqli_error($link), mysqli_errno($link));
+
+ mysqli_autocommit($link, false);
+ if (!$res = mysqli_query($link, "SELECT id, label FROM test ORDER BY id ASC LIMIT 3", MYSQLI_USE_RESULT))
+ printf("[008] [%d] %s\n", mysqli_error($link), mysqli_errno($link));
+
+ $pid = pcntl_fork();
+
+ switch ($pid) {
+ case -1:
+ printf("[009] Cannot fork child");
+ break;
+
+ case 0:
+ /* child */
+ if (!($plink = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) || !mysqli_autocommit($plink, true))
+ exit(mysqli_errno($plink));
+
+ $sql = sprintf("INSERT INTO messages(pid, sender, msg) VALUES (%d, 'child', '%%s')", posix_getpid());
+ if (!mysqli_query($plink, sprintf($sql, 'start')))
+ exit(mysqli_errno($plink));
+
+ $parent_sql = sprintf("SELECT msg_id, msg_time, msg FROM messages WHERE pid = %d AND sender = 'parent' ORDER BY msg_id DESC LIMIT 1", posix_getppid());
+ $msg_id = 0;
+ while ($row = mysqli_fetch_assoc($res)) {
+ /* send row to parent */
+ ob_start();
+ var_dump($row);
+ $tmp = ob_get_contents();
+ ob_end_clean();
+ if (!mysqli_query($plink, sprintf($sql, $tmp)))
+ exit(mysqli_errno($plink));
+
+ /* let the parent reply... */
+ $start = time();
+ do {
+ usleep(100);
+ if (!$pres = mysqli_query($plink, $parent_sql))
+ continue;
+ $tmp = mysqli_fetch_assoc($pres);
+ mysqli_free_result($pres);
+ if ($tmp['msg_id'] == $msg_id)
+ /* no new message */
+ continue;
+ if ($tmp['msg'] == 'stop')
+ break 2;
+ $msg_id = $tmp['msg_id'];
+ break;
+ } while ((time() - $start) < 5);
+
+ }
+
+ if (!mysqli_query($plink, sprintf($sql, 'stop')) || !mysqli_commit($link))
+ exit(mysqli_errno($plink));
+ exit(0);
+ break;
+
+ default:
+ /* parent */
+ if (!$plink = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[010] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ $status = null;
+ $start = time();
+ $sql = sprintf("SELECT msg_id, msg_time, msg FROM messages WHERE pid = %d AND sender = 'child' ORDER BY msg_id DESC LIMIT 1", $pid);
+ $parent_sql = sprintf("INSERT INTO messages (pid, sender, msg) VALUES (%d, 'parent', '%%s')", posix_getpid());
+ $last_msg_id = 0;
+ $num_rows = 0;
+ do {
+ $wait_id = pcntl_waitpid($pid, $status, WNOHANG);
+ if ($pres = mysqli_query($plink, $sql)) {
+ $row = mysqli_fetch_assoc($pres);
+ if ($row['msg_id'] != $last_msg_id) {
+ $last_msg_id = $row['msg_id'];
+ switch ($row['msg']) {
+ case 'start':
+ break;
+ case 'stop':
+ break 2;
+ default:
+ /* client has started fetching rows */
+ $client_row = $row['msg'];
+
+ $num_rows++;
+ if ($num_rows > 3) {
+ printf("[011] Child has fetched more than three rows!\n");
+ var_dump($client_row);
+ if (!mysqli_query($plink, sprintf($parent_sql, 'stop'))) {
+ printf("[012] Parent cannot inform child\n", mysqli_errno($plink), mysqli_error($plink));
+ }
+ break 2;
+ }
+
+ if (!$parent_row = mysqli_fetch_assoc($res)) {
+ printf("[013] Parent cannot fetch row %d\n", $num_rows, mysqli_errno($link), mysqli_error($link));
+ if (!mysqli_query($plink, sprintf($parent_sql, 'stop'))) {
+ printf("[014] Parent cannot inform child\n", mysqli_errno($plink), mysqli_error($plink));
+ }
+ break 2;
+ }
+
+ ob_start();
+ var_dump($parent_row);
+ $parent_row = ob_get_contents();
+ ob_end_clean();
+
+ if ($parent_row != $client_row) {
+ printf("[015] Child indicates different results than parent.\n");
+ var_dump($child_row);
+ var_dump($parent_row);
+ if (!mysqli_query($plink, sprintf($parent_sql, 'stop'))) {
+ printf("[016] Parent cannot inform child\n", mysqli_errno($plink), mysqli_error($plink));
+ }
+ break 2;
+ }
+
+ if (!mysqli_query($plink, sprintf($parent_sql, 'continue'))) {
+ printf("[017] Parent cannot inform child to continue.\n", mysqli_errno($plink), mysqli_error($plink));
+ }
+ break;
+ }
+ }
+ mysqli_free_result($pres);
+ }
+ usleep(100);
+ } while (((time() - $start) < 5) && ($num_rows < 3));
+ mysqli_close($plink);
+ $wait_id = pcntl_waitpid($pid, $status);
+ if (pcntl_wifexited($status) && (0 != ($tmp = pcntl_wexitstatus($status)))) {
+ printf("Exit code: %s\n", (pcntl_wifexited($status)) ? pcntl_wexitstatus($status) : 'n/a');
+ printf("Signal: %s\n", (pcntl_wifsignaled($status)) ? pcntl_wtermsig($status) : 'n/a');
+ printf("Stopped: %d\n", (pcntl_wifstopped($status)) ? pcntl_wstopsig($status) : 'n/a');
+ }
+ break;
+ }
+ mysqli_free_result($res);
+ mysqli_close($link);
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[018] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ if (!$res = mysqli_query($link, "SELECT sender, msg FROM messages ORDER BY msg_id ASC"))
+ printf("[019] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ while ($row = mysqli_fetch_assoc($res))
+ printf("%10s %s\n", $row['sender'], substr($row['msg'], 0, 5));
+ mysqli_free_result($res);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS test"))
+ printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS messages"))
+ printf("[c003] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+mysqli_close($link);
+?>
+--EXPECTF--
+array(1) {
+ ["message"]=>
+ string(20) "dumped by the parent"
+}
+ child start
+ child array
+ parent conti
+ child array
+ parent conti
+ child array
+ parent conti
+ child stop
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_free_result.phpt b/ext/mysqli/tests/mysqli_free_result.phpt
new file mode 100644
index 0000000..28f338a
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_free_result.phpt
@@ -0,0 +1,78 @@
+--TEST--
+mysqli_free_result()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_free_result()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_free_result($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+ if (!$res = mysqli_query($link, "SELECT id FROM test ORDER BY id LIMIT 1")) {
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ print "a\n";
+ var_dump(mysqli_free_result($res));
+ print "b\n";
+ var_dump(mysqli_free_result($res));
+
+ if (!$res = mysqli_query($link, "SELECT id FROM test ORDER BY id LIMIT 1")) {
+ printf("[004] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+ print "c\n";
+ var_dump($res = mysqli_store_result($link));
+ var_dump(mysqli_error($link));
+ print "[005]\n";
+ var_dump(mysqli_free_result($res));
+
+ if (!$res = mysqli_query($link, "SELECT id FROM test ORDER BY id LIMIT 1")) {
+ printf("[006] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+ print "d\n";
+ var_dump($res = mysqli_use_result($link));
+ var_dump(mysqli_error($link));
+ print "[007]\n";
+ var_dump(mysqli_free_result($res));
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+a
+NULL
+b
+
+Warning: mysqli_free_result(): Couldn't fetch mysqli_result in %s on line %d
+NULL
+c
+bool(false)
+%s(0) ""
+[005]
+
+Warning: mysqli_free_result() expects parameter 1 to be mysqli_result, boolean given in %s on line %d
+NULL
+d
+bool(false)
+%s(0) ""
+[007]
+
+Warning: mysqli_free_result() expects parameter 1 to be mysqli_result, boolean given in %s on line %d
+NULL
+done!
diff --git a/ext/mysqli/tests/mysqli_get_charset.phpt b/ext/mysqli/tests/mysqli_get_charset.phpt
new file mode 100644
index 0000000..8f81b33
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_get_charset.phpt
@@ -0,0 +1,115 @@
+--TEST--
+mysqli_get_charset()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+if (!function_exists('mysqli_get_charset'))
+ die("skip: function not available");
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_get_charset()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_get_charset($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_set_charset($link, $link)))
+ printf("[003] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (!$res = mysqli_query($link, 'SELECT version() AS server_version'))
+ printf("[004] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ $tmp = mysqli_fetch_assoc($res);
+ mysqli_free_result($res);
+ $version = explode('.', $tmp['server_version']);
+ if (empty($version))
+ printf("[005] Cannot determine server version, need MySQL Server 4.1+ for the test!\n");
+
+ if ($version[0] <= 4 && $version[1] < 1)
+ printf("[006] Need MySQL Server 4.1+ for the test!\n");
+
+ if (!$res = mysqli_query($link, 'SELECT @@character_set_connection AS charset, @@collation_connection AS collation'))
+ printf("[007] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ $tmp = mysqli_fetch_assoc($res);
+ mysqli_free_result($res);
+ if (!($character_set_connection = $tmp['charset']) || !($collation_connection = $tmp['collation']))
+ printf("[008] Cannot determine current character set and collation\n");
+
+ if (!$res = mysqli_query($link, $sql = sprintf("SHOW CHARACTER SET LIKE '%s'", $character_set_connection)))
+ printf("[009] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ $tmp = mysqli_fetch_assoc($res);
+ if (empty($tmp))
+ printf("[010] Cannot fetch Maxlen and/or Comment, test will fail: $sql\n");
+
+ $maxlen = (isset($tmp['Maxlen'])) ? $tmp['Maxlen'] : '';
+ $comment = (isset($tmp['Description'])) ? $tmp['Description'] : '';
+
+ if (!$res = mysqli_query($link, sprintf("SHOW COLLATION LIKE '%s'", $collation_connection)))
+ printf("[011] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ $tmp = mysqli_fetch_assoc($res);
+ mysqli_free_result($res);
+ if (!($id = $tmp['Id']))
+ printf("[012] Cannot fetch Id/Number, test will fail\n");
+
+ if (!$res = mysqli_query($link, sprintf("SHOW VARIABLES LIKE 'character_sets_dir'")))
+ printf("[013] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ $tmp = mysqli_fetch_assoc($res);
+ mysqli_free_result($res);
+ if (!($character_sets_dir = $tmp['Value']))
+ printf("[014] Cannot fetch character_sets_dir, test will fail\n");
+
+ if (!is_object($charset = mysqli_get_charset($link)))
+ printf("[015] Expecting object/std_class, got %s/%s\n", gettype($charset), $charset);
+
+ if (!isset($charset->charset) ||
+ !in_array(gettype($charset->charset), array("string", "unicode")) ||
+ ($character_set_connection !== $charset->charset))
+ printf("[016] Expecting string/%s, got %s/%s\n", $character_set_connection, gettype($charset->charset), $charset->charset);
+ if (!isset($charset->collation) ||
+ !in_array(gettype($charset->collation), array("string", "unicode")) ||
+ ($collation_connection !== $charset->collation))
+ printf("[017] Expecting string/%s, got %s/%s\n", $collation_connection, gettype($charset->collation), $charset->collation);
+
+ if (!isset($charset->dir) ||
+ !is_string($charset->dir))
+ printf("[019] Expecting string - ideally %s*, got %s/%s\n", $character_sets_dir, gettype($charset->dir), $charset->dir);
+
+ if (!isset($charset->min_length) ||
+ !(is_int($charset->min_length)) ||
+ ($charset->min_length < 0) ||
+ ($charset->min_length > $charset->max_length))
+ printf("[020] Expecting int between 0 ... %d, got %s/%s\n", $charset->max_length,
+ gettype($charset->min_length), $charset->min_length);
+
+ if (!isset($charset->number) ||
+ !is_int($charset->number) ||
+ ($charset->number !== (int)$id))
+ printf("[021] Expecting int/%d, got %s/%s\n", $id, gettype($charset->number), $charset->number);
+
+ if (!isset($charset->state) ||
+ !is_int($charset->state))
+ printf("[022] Expecting int/any, got %s/%s\n", gettype($charset->state), $charset->state);
+
+ mysqli_close($link);
+
+ if (NULL !== ($tmp = mysqli_get_charset($link)))
+ printf("[023] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Warning: mysqli_get_charset(): Couldn't fetch mysqli in %s on line %d
+done!
diff --git a/ext/mysqli/tests/mysqli_get_client_info.phpt b/ext/mysqli/tests/mysqli_get_client_info.phpt
new file mode 100644
index 0000000..bb3f5cc
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_get_client_info.phpt
@@ -0,0 +1,18 @@
+--TEST--
+mysqli_get_client_info()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+ if (!is_string($info = mysqli_get_client_info()) || ('' === $info))
+ printf("[001] Expecting string/any_non_empty, got %s/%s\n", gettype($info), $info);
+
+ print "done!";
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_get_client_stats.phpt b/ext/mysqli/tests/mysqli_get_client_stats.phpt
new file mode 100644
index 0000000..ef5ef6e
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_get_client_stats.phpt
@@ -0,0 +1,1294 @@
+--TEST--
+mysqli_get_client_stats()
+--SKIPIF--
+<?PHP
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+if (!function_exists('mysqli_get_client_stats')) {
+ die("skip only available with mysqlnd");
+}
+?>
+--INI--
+mysqlnd.collect_statistics=1
+mysqlnd.collect_memory_statistics=1
+--FILE--
+<?php
+ /*
+ TODO
+ no_index_used - difficult to simulate because server/engine dependent
+ bad_index_used - difficult to simulate because server/engine dependent
+ flushed_normal_sets
+ flushed_ps_sets
+ explicit_close
+ implicit_close
+ disconnect_close
+ in_middle_of_command_close
+ explicit_free_result
+ implicit_free_result
+ explicit_stmt_close
+ implicit_stmt_close
+ */
+
+ function mysqli_get_client_stats_assert_eq($field, $current, $expected, &$test_counter, $desc = "") {
+
+ $test_counter++;
+ if (is_array($current) && is_array($expected)) {
+ if ($current[$field] !== $expected[$field]) {
+ printf("[%03d] %s Expecting %s = %s/%s, got %s/%s\n",
+ $test_counter, $desc,
+ $field, $expected[$field], gettype($expected[$field]),
+ $current[$field], gettype($current[$field]));
+ }
+ } else if (is_array($current)) {
+ if ($current[$field] !== $expected) {
+ printf("[%03d] %s Expecting %s = %s/%s, got %s/%s\n",
+ $test_counter, $desc,
+ $field, $expected, gettype($expected),
+ $current[$field], gettype($current[$field]));
+ }
+ } else {
+ if ($current !== $expected) {
+ printf("[%03d] %s Expecting %s = %s/%s, got %s/%s\n",
+ $test_counter, $desc,
+ $field, $expected, gettype($expected),
+ $current, gettype($current));
+ }
+ }
+
+ }
+
+ function mysqli_get_client_stats_assert_gt($field, $current, $expected, &$test_counter, $desc = "") {
+
+ $test_counter++;
+ if (is_array($current) && is_array($expected)) {
+ if ($current[$field] <= $expected[$field]) {
+ printf("[%03d] %s Expecting %s > %s/%s, got %s/%s\n",
+ $test_counter, $desc,
+ $field, $expected[$field], gettype($expected[$field]),
+ $current[$field], gettype($current[$field]));
+ }
+ } else {
+ if ($current <= $expected) {
+ printf("[%03d] %s Expecting %s > %s/%s, got %s/%s\n",
+ $test_counter, $desc, $field,
+ $expected, gettype($expected),
+ $current, gettype($current));
+ }
+ }
+
+ }
+
+
+ $tmp = $link = null;
+ if (!is_null($tmp = @mysqli_get_client_stats($link)))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require_once("connect.inc");
+
+ if (!is_array($info = mysqli_get_client_stats()) || empty($info))
+ printf("[002] Expecting array/any_non_empty, got %s/%s\n", gettype($info), $info);
+
+ var_dump($info);
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ printf("[003] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+ exit(1);
+ }
+
+ if (!is_array($new_info = mysqli_get_client_stats()) || empty($new_info))
+ printf("[004] Expecting array/any_non_empty, got %s/%s\n", gettype($new_info), $new_info);
+
+ if (count($info) != count($new_info)) {
+ printf("[005] Expecting the same number of entries in the arrays\n");
+ var_dump($info);
+ var_dump($new_info);
+ }
+
+ $test_counter = 6;
+
+ mysqli_get_client_stats_assert_gt('bytes_sent', $new_info, $info, $test_counter);
+ mysqli_get_client_stats_assert_gt('bytes_received', $new_info, $info, $test_counter);
+ mysqli_get_client_stats_assert_gt('packets_sent', $new_info, $info, $test_counter);
+ mysqli_get_client_stats_assert_gt('packets_received', $new_info, $info, $test_counter);
+ mysqli_get_client_stats_assert_gt('protocol_overhead_in', $new_info, $info, $test_counter);
+ mysqli_get_client_stats_assert_gt('protocol_overhead_out', $new_info, $info, $test_counter);
+
+ // we assume the above as tested and in the following we check only those
+ mysqli_get_client_stats_assert_eq('result_set_queries', $new_info, $info, $test_counter);
+
+ /* we need to skip this test in unicode - we send set names utf8 during mysql_connect */
+ if (!(version_compare(PHP_VERSION, '5.9.9', '>') == 1))
+ mysqli_get_client_stats_assert_eq('non_result_set_queries', $new_info, $info, $test_counter);
+ mysqli_get_client_stats_assert_eq('buffered_sets', $new_info, $info, $test_counter);
+ mysqli_get_client_stats_assert_eq('unbuffered_sets', $new_info, $info, $test_counter);
+ mysqli_get_client_stats_assert_eq('ps_buffered_sets', $new_info, $info, $test_counter);
+ mysqli_get_client_stats_assert_eq('ps_unbuffered_sets', $new_info, $info, $test_counter);
+
+ mysqli_get_client_stats_assert_eq('rows_skipped_ps', $new_info, $info, $test_counter);
+ mysqli_get_client_stats_assert_eq('copy_on_write_saved', $new_info, $info, $test_counter);
+ mysqli_get_client_stats_assert_eq('copy_on_write_performed', $new_info, $info, $test_counter);
+ mysqli_get_client_stats_assert_eq('command_buffer_too_small', $new_info, $info, $test_counter);
+ // This is not a mistake that I use %unicode|string%(1) "1" here! Andrey did not go for int to avoid any
+ // issues for very large numbers and 32 vs. 64bit systems
+ mysqli_get_client_stats_assert_eq('connect_success', $new_info, "1", $test_counter);
+ mysqli_get_client_stats_assert_eq('connect_failure', $new_info, $info, $test_counter);
+ mysqli_get_client_stats_assert_eq('connection_reused', $new_info, $info, $test_counter);
+
+ // No data fetched so far
+ mysqli_get_client_stats_assert_eq('bytes_received_real_data_normal', $new_info, "0", $test_counter);
+ mysqli_get_client_stats_assert_eq('bytes_received_real_data_ps', $new_info, "0", $test_counter);
+
+ require('table.inc');
+ if (!is_array($info = mysqli_get_client_stats()) || empty($info))
+ printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+ ++$test_counter, gettype($info), $info);
+
+ // fetch stats
+ $expected = $info;
+
+ // buffered normal
+ print "Testing buffered normal...\n";
+ if (!$res = mysqli_query($link, 'SELECT COUNT(*) AS _num FROM test', MYSQLI_STORE_RESULT))
+ printf("[%03d] SELECT COUNT() FROM test failed, [%d] %s\n",
+ ++$test_counter, mysqli_errno($link), mysqli_error($link));
+
+ $expected['rows_fetched_from_server_normal'] = (string)($expected['rows_fetched_from_server_normal'] + 1);
+ $expected['buffered_sets'] = (string)($expected['buffered_sets'] + 1);
+ $expected['result_set_queries'] = (string)($expected['result_set_queries'] + 1);
+ $expected['rows_buffered_from_client_normal'] = (string)($expected['rows_buffered_from_client_normal'] + 1);
+
+ if (!is_array($info = mysqli_get_client_stats()) || empty($info))
+ printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+ ++$test_counter, gettype($info), $info);
+
+ mysqli_get_client_stats_assert_gt('bytes_sent', $info, $expected, $test_counter);
+ mysqli_get_client_stats_assert_gt('bytes_received', $info, $expected, $test_counter);
+
+ // real_data_* get incremeneted after mysqli_*fetch*()
+ mysqli_get_client_stats_assert_eq('bytes_received_real_data_normal', $info, "0", $test_counter);
+ mysqli_get_client_stats_assert_eq('bytes_received_real_data_ps', $info, "0", $test_counter);
+
+ mysqli_get_client_stats_assert_eq('rows_fetched_from_server_normal', $info, $expected, $test_counter);
+ mysqli_get_client_stats_assert_eq('rows_fetched_from_client_normal_buffered', $info, $expected, $test_counter);
+ mysqli_get_client_stats_assert_eq('buffered_sets', $info, $expected, $test_counter);
+ mysqli_get_client_stats_assert_eq('result_set_queries', $info, $expected, $test_counter);
+ mysqli_get_client_stats_assert_eq('rows_buffered_from_client_normal', $info, $expected, $test_counter);
+
+ /* no change to rows_fetched_from_client_normal_buffered! */
+ if (!$row = mysqli_fetch_assoc($res))
+ printf("[%03d] fetch_assoc - SELECT COUNT() FROM test failed, [%d] %s\n",
+ ++$test_counter, mysqli_errno($link), mysqli_error($link));
+
+ $expected['rows_fetched_from_client_normal_buffered'] = (string)($expected['rows_fetched_from_client_normal_buffered'] + 1);
+
+ if (!is_array($info = mysqli_get_client_stats()) || empty($info))
+ printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+ ++$test_counter, gettype($info), $info);
+
+ // fetch will increment
+ mysqli_get_client_stats_assert_gt('bytes_received_real_data_normal', $info, $expected, $test_counter);
+ $expected['bytes_received_real_data_normal'] = $info['bytes_received_real_data_normal'];
+ mysqli_get_client_stats_assert_eq('bytes_received_real_data_ps', $info, "0", $test_counter);
+
+ mysqli_get_client_stats_assert_eq('rows_fetched_from_server_normal', $info, $expected, $test_counter);
+ mysqli_get_client_stats_assert_eq('rows_fetched_from_client_normal_buffered', $info, $expected, $test_counter);
+ mysqli_get_client_stats_assert_eq('rows_buffered_from_client_normal', $info, $expected, $test_counter);
+
+ $num_rows = $row['_num'];
+ mysqli_free_result($res);
+
+ print "Testing buffered normal... - SELECT id, label FROM test\n";
+ if (!$res = mysqli_query($link, 'SELECT id, label FROM test', MYSQLI_STORE_RESULT))
+ printf("[%03d] SELECT id, label FROM test failed, [%d] %s\n",
+ ++$test_counter, mysqli_errno($link), mysqli_error($link));
+
+
+ assert(mysqli_num_rows($res) == $num_rows);
+
+ if (!is_array($info = mysqli_get_client_stats()) || empty($info))
+ printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+ ++$test_counter, gettype($info), $info);
+
+
+ $expected['rows_fetched_from_server_normal'] = (string)($expected['rows_fetched_from_server_normal'] + $num_rows);
+ $expected['rows_buffered_from_client_normal'] = (string)($expected['rows_buffered_from_client_normal'] + $num_rows);
+ $expected['buffered_sets'] = (string)($expected['buffered_sets'] + 1);
+ $expected['result_set_queries'] = (string)($expected['result_set_queries'] + 1);
+
+ mysqli_get_client_stats_assert_eq('bytes_received_real_data_normal', $info, $expected, $test_counter);
+
+ mysqli_get_client_stats_assert_eq('rows_fetched_from_server_normal', $info, $expected, $test_counter);
+ mysqli_get_client_stats_assert_eq('rows_fetched_from_client_normal_buffered', $info, $expected, $test_counter);
+ mysqli_get_client_stats_assert_eq('buffered_sets', $info, $expected, $test_counter);
+ mysqli_get_client_stats_assert_eq('result_set_queries', $info, $expected, $test_counter);
+ mysqli_get_client_stats_assert_eq('rows_buffered_from_client_normal', $info, $expected, $test_counter);
+ mysqli_get_client_stats_assert_eq('rows_buffered_from_client_normal', $info, $expected, $test_counter);
+
+ /* fetching none, but stats should not be affected - current implementation */
+ mysqli_free_result($res);
+
+ if (!is_array($info = mysqli_get_client_stats()) || empty($info))
+ printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+ ++$test_counter, gettype($info), $info);
+
+
+ mysqli_get_client_stats_assert_eq('bytes_received_real_data_normal', $info, $expected, $test_counter);
+ mysqli_get_client_stats_assert_eq('rows_fetched_from_server_normal', $info, $expected, $test_counter);
+ mysqli_get_client_stats_assert_eq('rows_fetched_from_client_normal_buffered', $info, $expected, $test_counter);
+
+ print "Testing unbuffered normal...\n";
+ if (!$res = mysqli_query($link, 'SELECT id, label FROM test', MYSQLI_USE_RESULT))
+ printf("[%03d] SELECT id, label FROM test failed, [%d] %s\n",
+ ++$test_counter, mysqli_errno($link), mysqli_error($link));
+
+ if (!is_array($info = mysqli_get_client_stats()) || empty($info))
+ printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+ ++$test_counter, gettype($info), $info);
+
+ mysqli_get_client_stats_assert_eq('rows_fetched_from_server_normal', $info, $expected, $test_counter);
+ mysqli_get_client_stats_assert_eq('rows_fetched_from_client_normal_unbuffered', $info, $expected, $test_counter);
+ mysqli_get_client_stats_assert_eq('bytes_received_real_data_normal', $info, $expected, $test_counter);
+
+ while ($row = mysqli_fetch_assoc($res))
+ ;
+ mysqli_free_result($res);
+
+ $expected['rows_fetched_from_server_normal'] = (string)($expected['rows_fetched_from_server_normal'] + $num_rows);
+ $expected['rows_fetched_from_client_normal_unbuffered'] = (string)($expected['rows_fetched_from_client_normal_unbuffered'] + $num_rows);
+ $expected['unbuffered_sets'] = (string)($expected['unbuffered_sets'] + 1);
+ $expected['result_set_queries'] = (string)($expected['result_set_queries'] + 1);
+
+ if (!is_array($info = mysqli_get_client_stats()) || empty($info))
+ printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+ ++$test_counter, gettype($info), $info);
+
+ mysqli_get_client_stats_assert_gt('bytes_received_real_data_normal', $info, $expected, $test_counter);
+ $expected['bytes_received_real_data_normal'] = $info['bytes_received_real_data_normal'];
+
+ mysqli_get_client_stats_assert_eq('rows_fetched_from_server_normal', $info, $expected, $test_counter);
+ mysqli_get_client_stats_assert_eq('rows_fetched_from_client_normal_unbuffered', $info, $expected, $test_counter);
+ mysqli_get_client_stats_assert_eq('unbuffered_sets', $info, $expected, $test_counter);
+ mysqli_get_client_stats_assert_eq('result_set_queries', $info, $expected, $test_counter);
+
+ print "Testing unbuffered normal... - SELECT id, label FROM test, not all fetched\n";
+ if (!$res = mysqli_query($link, 'SELECT id, label FROM test', MYSQLI_USE_RESULT))
+ printf("[%03d] SELECT id, label FROM test failed, [%d] %s\n",
+ ++$test_counter, mysqli_errno($link), mysqli_error($link));
+
+ for ($i = 0; $i < $num_rows - 1; $i++)
+ $row = mysqli_fetch_assoc($res);
+
+ $expected['rows_fetched_from_server_normal'] = (string)($expected['rows_fetched_from_server_normal'] + $num_rows - 1);
+ $expected['rows_fetched_from_client_normal_unbuffered'] = (string)($expected['rows_fetched_from_client_normal_unbuffered'] + $num_rows - 1);
+ $expected['unbuffered_sets'] = (string)($expected['unbuffered_sets'] + 1);
+ $expected['result_set_queries'] = (string)($expected['result_set_queries'] + 1);
+
+ if (!is_array($info = mysqli_get_client_stats()) || empty($info))
+ printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+ ++$test_counter, gettype($info), $info);
+
+ mysqli_get_client_stats_assert_gt('bytes_received_real_data_normal', $info, $expected, $test_counter);
+ $expected['bytes_received_real_data_normal'] = $info['bytes_received_real_data_normal'];
+
+ mysqli_get_client_stats_assert_eq('rows_fetched_from_server_normal', $info, $expected, $test_counter);
+ mysqli_get_client_stats_assert_eq('rows_fetched_from_client_normal_unbuffered', $info, $expected, $test_counter);
+ mysqli_get_client_stats_assert_eq('unbuffered_sets', $info, $expected, $test_counter);
+ mysqli_get_client_stats_assert_eq('result_set_queries', $info, $expected, $test_counter);
+
+ print "Testing if implicit fetching and cleaning happens...\n";
+ mysqli_free_result($res);
+
+ /* last row has been implicitly cleaned from the wire by freeing the result set */
+ $expected['rows_fetched_from_server_normal'] = (string)($expected['rows_fetched_from_server_normal'] + 1);
+ $expected['rows_fetched_from_client_normal_unbuffered'] = (string)($expected['rows_fetched_from_client_normal_unbuffered'] + 1);
+ $expected['rows_skipped_normal'] = (string)($info['rows_skipped_normal'] + 1);
+ $expected['flushed_normal_sets'] = (string)($expected['flushed_normal_sets'] + 1);
+
+ if (!is_array($info = mysqli_get_client_stats()) || empty($info))
+ printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+ ++$test_counter, gettype($info), $info);
+
+ mysqli_get_client_stats_assert_eq('bytes_received_real_data_normal', $info, $expected, $test_counter);
+
+ mysqli_get_client_stats_assert_eq('rows_fetched_from_server_normal', $info, $expected, $test_counter);
+ mysqli_get_client_stats_assert_eq('rows_fetched_from_client_normal_unbuffered', $info, $expected, $test_counter);
+ mysqli_get_client_stats_assert_eq('rows_skipped_normal', $info, $expected, $test_counter);
+ mysqli_get_client_stats_assert_eq('flushed_normal_sets', $info, $expected, $test_counter);
+
+ print "Testing buffered Prepared Statements...\n";
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[%03d] stmt_init() failed, [%d] %s\n",
+ ++$test_counter, mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_stmt_prepare($stmt, 'SELECT id, label FROM test') ||
+ !mysqli_stmt_execute($stmt))
+ printf("[%03d] prepare/execute failed, [%d] %s\n",
+ ++$test_counter, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ /* by default PS is unbuffered - no change */
+ mysqli_get_client_stats_assert_eq('rows_fetched_from_server_ps', $info, $expected, $test_counter);
+ mysqli_get_client_stats_assert_eq('rows_fetched_from_client_ps_buffered', $info, $expected, $test_counter);
+
+ if (!mysqli_stmt_store_result($stmt))
+ printf("[%03d] store_result failed, [%d] %s\n",
+ ++$test_counter, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ mysqli_stmt_free_result($stmt);
+
+ mysqli_get_client_stats_assert_eq('bytes_received_real_data_ps', $info, "0", $test_counter);
+ mysqli_get_client_stats_assert_eq('bytes_received_real_data_normal', $info, $expected, $test_counter);
+
+ $expected['rows_fetched_from_server_ps'] = (string)($expected['rows_fetched_from_server_ps'] + $num_rows);
+ $expected['result_set_queries'] = (string)($expected['result_set_queries'] + 1);
+ $expected['ps_buffered_sets'] = (string)($expected['ps_buffered_sets'] + 1);
+ $expected['rows_buffered_from_client_ps'] = (string)($expected['rows_buffered_from_client_ps'] + $num_rows);
+
+
+ if (!is_array($info = mysqli_get_client_stats()) || empty($info))
+ printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+ ++$test_counter, gettype($info), $info);
+
+ mysqli_get_client_stats_assert_eq('rows_fetched_from_server_ps', $info, $expected, $test_counter);
+ mysqli_get_client_stats_assert_eq('rows_fetched_from_client_ps_buffered', $info, $expected, $test_counter);
+ mysqli_get_client_stats_assert_eq('result_set_queries', $info, $expected, $test_counter);
+ mysqli_get_client_stats_assert_eq('ps_buffered_sets', $info, $expected, $test_counter);
+ mysqli_get_client_stats_assert_eq('rows_buffered_from_client_ps', $info, $expected, $test_counter);
+
+ mysqli_get_client_stats_assert_eq('bytes_received_real_data_ps', $info, "0", $test_counter);
+
+ print "Testing buffered Prepared Statements... - fetching all\n";
+
+ if (!mysqli_stmt_prepare($stmt, 'SELECT id, label FROM test') ||
+ !mysqli_stmt_execute($stmt))
+ printf("[%03d] prepare/execute failed, [%d] %s\n",
+ ++$test_counter, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = $label = null;
+ if (!mysqli_stmt_bind_result($stmt, $id, $label))
+ printf("[%03d] bind_result failed, [%d] %s\n",
+ ++$test_counter, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_store_result($stmt))
+ printf("[%03d] store_result failed, [%d] %s\n",
+ ++$test_counter, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ while (mysqli_stmt_fetch($stmt))
+ ;
+
+ $expected['rows_fetched_from_server_ps'] = (string)($expected['rows_fetched_from_server_ps'] + $num_rows);
+ $expected['rows_fetched_from_client_ps_buffered'] = (string)($expected['rows_fetched_from_client_ps_buffered'] + $num_rows);
+ $expected['result_set_queries'] = (string)($expected['result_set_queries'] + 1);
+ $expected['ps_buffered_sets'] = (string)($expected['ps_buffered_sets'] + 1);
+ $expected['rows_buffered_from_client_ps'] = (string)($expected['rows_buffered_from_client_ps'] + $num_rows);
+
+ if (!is_array($info = mysqli_get_client_stats()) || empty($info))
+ printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+ ++$test_counter, gettype($info), $info);
+
+
+ mysqli_get_client_stats_assert_gt('bytes_received_real_data_ps', $info, $expected, $test_counter);
+ $expected['bytes_received_real_data_ps'] = $info['bytes_received_real_data_ps'];
+
+ mysqli_get_client_stats_assert_eq('rows_fetched_from_server_ps', $info, $expected, $test_counter);
+ mysqli_get_client_stats_assert_eq('rows_fetched_from_client_ps_buffered', $info, $expected, $test_counter);
+ mysqli_get_client_stats_assert_eq('result_set_queries', $info, $expected, $test_counter);
+ mysqli_get_client_stats_assert_eq('ps_buffered_sets', $info, $expected, $test_counter);
+ mysqli_get_client_stats_assert_eq('rows_buffered_from_client_ps', $info, $expected, $test_counter);
+
+ mysqli_stmt_free_result($stmt);
+
+ print "Testing buffered Prepared Statements... - fetching all but one\n";
+
+ if (!mysqli_stmt_prepare($stmt, 'SELECT id, label FROM test') ||
+ !mysqli_stmt_execute($stmt))
+ printf("[%03d] prepare/execute failed, [%d] %s\n",
+ ++$test_counter, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = $label = null;
+ if (!mysqli_stmt_bind_result($stmt, $id, $label))
+ printf("[%03d] bind_result failed, [%d] %s\n",
+ ++$test_counter, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_store_result($stmt))
+ printf("[%03d] store_result failed, [%d] %s\n",
+ ++$test_counter, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ for ($i = 0; $i < $num_rows - 1; $i++)
+ mysqli_stmt_fetch($stmt);
+
+ $expected['rows_fetched_from_server_ps'] = (string)($expected['rows_fetched_from_server_ps'] + $num_rows);
+ $expected['rows_fetched_from_client_ps_buffered'] = (string)($expected['rows_fetched_from_client_ps_buffered'] + $num_rows - 1);
+ $expected['result_set_queries'] = (string)($expected['result_set_queries'] + 1);
+ $expected['ps_buffered_sets'] = (string)($expected['ps_buffered_sets'] + 1);
+ $expected['rows_buffered_from_client_ps'] = (string)($expected['rows_buffered_from_client_ps'] + $num_rows);
+
+ if (!is_array($info = mysqli_get_client_stats()) || empty($info))
+ printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+ ++$test_counter, gettype($info), $info);
+
+ mysqli_get_client_stats_assert_gt('bytes_received_real_data_ps', $info, $expected, $test_counter);
+ $expected['bytes_received_real_data_ps'] = $info['bytes_received_real_data_ps'];
+
+ mysqli_get_client_stats_assert_eq('rows_fetched_from_server_ps', $info, $expected, $test_counter);
+ mysqli_get_client_stats_assert_eq('rows_fetched_from_client_ps_buffered', $info, $expected, $test_counter);
+ mysqli_get_client_stats_assert_eq('result_set_queries', $info, $expected, $test_counter);
+ mysqli_get_client_stats_assert_eq('ps_buffered_sets', $info, $expected, $test_counter);
+ mysqli_get_client_stats_assert_eq('rows_buffered_from_client_ps', $info, $expected, $test_counter);
+
+ $expected['rows_skipped_ps'] = $info['rows_skipped_ps'];
+ mysqli_stmt_free_result($stmt);
+
+ if (!is_array($info = mysqli_get_client_stats()) || empty($info))
+ printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+ ++$test_counter, gettype($info), $info);
+
+ /* buffered result set - no skipping possible! */
+ mysqli_get_client_stats_assert_eq('rows_skipped_ps', $info, $expected, $test_counter);
+
+ print "Testing unbuffered Prepared Statements... - fetching all\n";
+
+ if (!mysqli_stmt_prepare($stmt, 'SELECT id, label FROM test') ||
+ !mysqli_stmt_execute($stmt))
+ printf("[%03d] prepare/execute failed, [%d] %s\n",
+ ++$test_counter, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = $label = null;
+ if (!mysqli_stmt_bind_result($stmt, $id, $label))
+ printf("[%03d] bind_result failed, [%d] %s\n",
+ ++$test_counter, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $i = 0;
+ while (mysqli_stmt_fetch($stmt))
+ $i++;
+ assert($num_rows = $i);
+
+ $expected['rows_fetched_from_server_ps'] = (string)($expected['rows_fetched_from_server_ps'] + $num_rows);
+ $expected['rows_fetched_from_client_ps_unbuffered'] = (string)($expected['rows_fetched_from_client_ps_unbuffered'] + $num_rows);
+ $expected['result_set_queries'] = (string)($expected['result_set_queries'] + 1);
+ $expected['ps_unbuffered_sets'] = (string)($expected['ps_unbuffered_sets'] + 1);
+
+ if (!is_array($info = mysqli_get_client_stats()) || empty($info))
+ printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+ ++$test_counter, gettype($info), $info);
+
+ mysqli_get_client_stats_assert_gt('bytes_received_real_data_ps', $info, $expected, $test_counter);
+ $expected['bytes_received_real_data_ps'] = $info['bytes_received_real_data_ps'];
+
+ mysqli_get_client_stats_assert_eq('rows_fetched_from_server_ps', $info, $expected, $test_counter);
+ mysqli_get_client_stats_assert_eq('rows_fetched_from_client_ps_unbuffered', $info, $expected, $test_counter);
+ mysqli_get_client_stats_assert_eq('result_set_queries', $info, $expected, $test_counter);
+ mysqli_get_client_stats_assert_eq('ps_unbuffered_sets', $info, $expected, $test_counter);
+ mysqli_get_client_stats_assert_eq('rows_buffered_from_client_ps', $info, $expected, $test_counter);
+
+ mysqli_stmt_free_result($stmt);
+
+ print "Testing unbuffered Prepared Statements... - fetching all but one\n";
+
+ if (!mysqli_stmt_prepare($stmt, 'SELECT id, label FROM test') ||
+ !mysqli_stmt_execute($stmt))
+ printf("[%03d] prepare/execute failed, [%d] %s\n",
+ ++$test_counter, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = $label = null;
+ if (!mysqli_stmt_bind_result($stmt, $id, $label))
+ printf("[%03d] bind_result failed, [%d] %s\n",
+ ++$test_counter, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ for ($i = 0; $i < $num_rows - 1; $i++)
+ mysqli_stmt_fetch($stmt);
+
+ $expected['rows_fetched_from_server_ps'] = (string)($expected['rows_fetched_from_server_ps'] + $num_rows - 1);
+ $expected['rows_fetched_from_client_ps_unbuffered'] = (string)($expected['rows_fetched_from_client_ps_unbuffered'] + $num_rows - 1);
+ $expected['result_set_queries'] = (string)($expected['result_set_queries'] + 1);
+ $expected['ps_unbuffered_sets'] = (string)($expected['ps_unbuffered_sets'] + 1);
+
+ if (!is_array($info = mysqli_get_client_stats()) || empty($info))
+ printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+ ++$test_counter, gettype($info), $info);
+
+ mysqli_get_client_stats_assert_gt('bytes_received_real_data_ps', $info, $expected, $test_counter);
+ $expected['bytes_received_real_data_ps'] = $info['bytes_received_real_data_ps'];
+
+ mysqli_get_client_stats_assert_eq('rows_fetched_from_server_ps', $info, $expected, $test_counter);
+ mysqli_get_client_stats_assert_eq('rows_fetched_from_client_ps_unbuffered', $info, $expected, $test_counter);
+ mysqli_get_client_stats_assert_eq('result_set_queries', $info, $expected, $test_counter);
+ mysqli_get_client_stats_assert_eq('ps_unbuffered_sets', $info, $expected, $test_counter);
+ mysqli_get_client_stats_assert_eq('rows_buffered_from_client_ps', $info, $expected, $test_counter);
+
+ mysqli_stmt_free_result($stmt);
+ $expected['rows_skipped_ps'] = (string)($expected['rows_skipped_ps'] + 1);
+ $expected['flushed_ps_sets'] = (string)($expected['flushed_ps_sets'] + 1);
+ $expected['rows_fetched_from_server_ps'] = (string)($expected['rows_fetched_from_server_ps'] + 1);
+
+ if (!is_array($info = mysqli_get_client_stats()) || empty($info))
+ printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+ ++$test_counter, gettype($info), $info);
+
+ mysqli_get_client_stats_assert_eq('bytes_received_real_data_ps', $info, $expected, $test_counter);
+
+ mysqli_get_client_stats_assert_eq('rows_skipped_ps', $info, $expected, $test_counter);
+ mysqli_get_client_stats_assert_eq('flushed_ps_sets', $info, $expected, $test_counter);
+ mysqli_get_client_stats_assert_eq('rows_fetched_from_server_ps', $info, $expected, $test_counter);
+
+ /*
+ print "Checking for normal buffered side effects...\n";
+ foreach ($info as $k => $v)
+ if ($info[$k] != $expected[$k])
+ printf("$k - $v != %s\n", $expected[$k]);
+ */
+ print "... done with fetch statistics\n";
+
+ if (!is_array($info = mysqli_get_client_stats()) || empty($info))
+ printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+ ++$test_counter, gettype($info), $info);
+
+ mysqli_get_client_stats_assert_eq('bytes_received_real_data_normal', $info, $expected, $test_counter);
+ mysqli_get_client_stats_assert_eq('bytes_received_real_data_ps', $info, $expected, $test_counter);
+
+ //
+ // result_set_queries statistics
+ //
+
+ if (!is_array($info = mysqli_get_client_stats()) || empty($info))
+ printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+ ++$test_counter, gettype($info), $info);
+
+ if (!$res = mysqli_query($link, "SELECT id, label FROM test"))
+ printf("[%03d] SELECT failed, [%d] %s\n", ++$test_counter,
+ mysqli_errno($link), mysqli_error($link));
+
+ $rows = 0;
+ while ($row = mysqli_fetch_assoc($res))
+ $rows++;
+
+ if (0 == $rows)
+ printf("[%03d] Expecting at least one result, [%d] %s\n", ++$test_counter,
+ mysqli_errno($link), mysqli_error($link));
+
+ mysqli_free_result($res);
+
+ if (!is_array($new_info = mysqli_get_client_stats()) || empty($new_info))
+ printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+ ++$test_counter, gettype($new_info), $new_info);
+
+ mysqli_get_client_stats_assert_eq('result_set_queries', $new_info, (string)($info['result_set_queries'] + 1), $test_counter);
+ $info = $new_info;
+
+ mysqli_get_client_stats_assert_gt('bytes_received_real_data_normal', $info, $expected, $test_counter);
+ $expected['bytes_received_real_data_normal'] = $info['bytes_received_real_data_normal'];
+
+ //
+ // non_result_set_queries - DDL
+ //
+
+ // CREATE TABLE, DROP TABLE
+ if (!mysqli_query($link, "DROP TABLE IF EXISTS non_result_set_queries_test"))
+ printf("[%03d] DROP TABLE failed, [%d] %s\n", ++$test_counter,
+ mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, "CREATE TABLE non_result_set_queries_test(id INT) ENGINE = " . $engine)) {
+ printf("[%03d] CREATE TABLE failed, [%d] %s\n", ++$test_counter,
+ mysqli_errno($link), mysqli_error($link));
+ } else {
+ if (!is_array($new_info = mysqli_get_client_stats()) || empty($new_info))
+ printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+ ++$test_counter, gettype($new_info), $new_info);
+ mysqli_get_client_stats_assert_eq('non_result_set_queries', $new_info, (string)($info['non_result_set_queries'] + 2), $test_counter, 'CREATE/DROP TABLE');
+ }
+ $info = $new_info;
+
+ // ALERT TABLE
+ if (!mysqli_query($link, "ALTER TABLE non_result_set_queries_test ADD label CHAR(1)")) {
+ printf("[%03d] ALTER TABLE failed, [%d] %s\n", ++$test_counter,
+ mysqli_errno($link), mysqli_error($link));
+ } else {
+ if (!is_array($new_info = mysqli_get_client_stats()) || empty($new_info))
+ printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+ ++$test_counter, gettype($new_info), $new_info);
+ mysqli_get_client_stats_assert_eq('non_result_set_queries', $new_info, (string)($info['non_result_set_queries'] + 1), $test_counter, 'ALTER TABLE');
+ }
+ $info = $new_info;
+
+ // CREATE INDEX, DROP INDEX
+ if (!mysqli_query($link, "CREATE INDEX idx_1 ON non_result_set_queries_test(id)")) {
+ printf("[%03d] CREATE INDEX failed, [%d] %s\n", ++$test_counter,
+ mysqli_errno($link), mysqli_error($link));
+ } else {
+
+ if (!mysqli_query($link, "DROP INDEX idx_1 ON non_result_set_queries_test"))
+ printf("[%03d] DROP INDEX failed, [%d] %s\n", ++$test_counter,
+ mysqli_errno($link), mysqli_error($link));
+
+ if (!is_array($new_info = mysqli_get_client_stats()) || empty($new_info))
+ printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+ ++$test_counter, gettype($new_info), $new_info);
+ mysqli_get_client_stats_assert_eq('non_result_set_queries', $new_info, (string)($info['non_result_set_queries'] + 2), $test_counter, 'DROP INDEX');
+ }
+ $info = $new_info;
+
+ // RENAME TABLE
+ if (!mysqli_query($link, "DROP TABLE IF EXISTS client_stats_test"))
+ printf("[%03d] Cleanup, DROP TABLE client_stats_test failed, [%d] %s\n", ++$test_counter,
+ mysqli_errno($link), mysqli_error($link));
+
+ if (!is_array($new_info = mysqli_get_client_stats()) || empty($new_info))
+ printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+ ++$test_counter, gettype($new_info), $new_info);
+ $info = $new_info;
+
+ if (!mysqli_query($link, "RENAME TABLE non_result_set_queries_test TO client_stats_test")) {
+ printf("[%03d] RENAME TABLE failed, [%d] %s\n", ++$test_counter,
+ mysqli_errno($link), mysqli_error($link));
+
+ } else {
+ if (!is_array($new_info = mysqli_get_client_stats()) || empty($new_info))
+ printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+ ++$test_counter, gettype($new_info), $new_info);
+ mysqli_get_client_stats_assert_eq('non_result_set_queries', $new_info, (string)($info['non_result_set_queries'] + 1), $test_counter, 'RENAME TABLE');
+
+ }
+ $info = $new_info;
+
+ if (!mysqli_query($link, "DROP TABLE IF EXISTS non_result_set_queries_test"))
+ printf("[%03d] Cleanup, DROP TABLE failed, [%d] %s\n", ++$test_counter,
+ mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, "DROP TABLE IF EXISTS client_stats_test"))
+ printf("[%03d] Cleanup, DROP TABLE failed, [%d] %s\n", ++$test_counter,
+ mysqli_errno($link), mysqli_error($link));
+
+ // Let's see if we have privileges for CREATE DATABASE
+ mysqli_query($link, "DROP DATABASE IF EXISTS mysqli_get_client_stats");
+ if (!is_array($new_info = mysqli_get_client_stats()) || empty($new_info))
+ printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+ ++$test_counter, gettype($new_info), $new_info);
+ $info = $new_info;
+
+
+ // CREATE, ALTER, RENAME, DROP DATABASE
+ if (mysqli_query($link, "CREATE DATABASE mysqli_get_client_stats")) {
+
+ if (!is_array($new_info = mysqli_get_client_stats()) || empty($new_info))
+ printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+ ++$test_counter, gettype($new_info), $new_info);
+ mysqli_get_client_stats_assert_eq('non_result_set_queries', $new_info, (string)($info['non_result_set_queries'] + 1), $test_counter, 'CREATE DATABASE');
+ $info = $new_info;
+
+ if (!mysqli_query($link, "ALTER DATABASE DEFAULT CHARACTER SET latin1"))
+ printf("[%03d] ALTER DATABASE failed, [%d] %s\n", ++$test_counter,
+ mysqli_errno($link), mysqli_error($link));
+
+ if (!is_array($new_info = mysqli_get_client_stats()) || empty($new_info))
+ printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+ ++$test_counter, gettype($new_info), $new_info);
+ mysqli_get_client_stats_assert_eq('non_result_set_queries', $new_info, (string)($info['non_result_set_queries'] + 1), $test_counter, 'CREATE DATABASE');
+ $info = $new_info;
+
+ if (mysqli_get_server_version($link) > 51700) {
+ if (!mysqli_query($link, "RENAME DATABASE mysqli_get_client_stats TO mysqli_get_client_stats_"))
+ printf("[%03d] RENAME DATABASE failed, [%d] %s\n", ++$test_counter,
+ mysqli_errno($link), mysqli_error($link));
+
+ if (!is_array($new_info = mysqli_get_client_stats()) || empty($new_info))
+ printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+ ++$test_counter, gettype($new_info), $new_info);
+ mysqli_get_client_stats_assert_eq('non_result_set_queries', $new_info, (string)($info['non_result_set_queries'] + 1), $test_counter, 'CREATE DATABASE');
+ $info = $new_info;
+ } else {
+ if (!mysqli_query($link, "CREATE DATABASE mysqli_get_client_stats_"))
+ printf("[%03d] CREATE DATABASE failed, [%d] %s\n", ++$test_counter,
+ mysqli_errno($link), mysqli_error($link));
+ if (!is_array($new_info = mysqli_get_client_stats()) || empty($new_info))
+ printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+ ++$test_counter, gettype($new_info), $new_info);
+ $info = $new_info;
+ }
+
+ if (!mysqli_query($link, "DROP DATABASE mysqli_get_client_stats_"))
+ printf("[%03d] DROP DATABASE failed, [%d] %s\n", ++$test_counter,
+ mysqli_errno($link), mysqli_error($link));
+
+ if (!is_array($new_info = mysqli_get_client_stats()) || empty($new_info))
+ printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+ ++$test_counter, gettype($new_info), $new_info);
+ mysqli_get_client_stats_assert_eq('non_result_set_queries', $new_info, (string)($info['non_result_set_queries'] + 1), $test_counter, 'DROP DATABASE');
+ $info = $new_info;
+ }
+
+ // CREATE SERVER, ALTER SERVER, DROP SERVER
+ // We don't really try to use federated, we just want to see if the syntax works
+ mysqli_query($link, "DROP SERVER IF EXISTS myself");
+
+ if (!is_array($new_info = mysqli_get_client_stats()) || empty($new_info))
+ printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+ ++$test_counter, gettype($new_info), $new_info);
+ $info = $new_info;
+
+ $sql = sprintf("CREATE SERVER myself FOREIGN DATA WRAPPER mysql OPTIONS (user '%s', password '%s', database '%s')",
+ $user, $passwd, $db);
+ if (mysqli_query($link, $sql)) {
+ // server knows about it
+
+ if (!is_array($new_info = mysqli_get_client_stats()) || empty($new_info))
+ printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+ ++$test_counter, gettype($new_info), $new_info);
+
+ mysqli_get_client_stats_assert_eq('non_result_set_queries', $new_info, (string)($info['non_result_set_queries'] + 1), $test_counter, 'CREATE SERVER');
+ $info = $new_info;
+
+ if (!mysqli_query($link, sprintf("ALTER SERVER myself OPTIONS(user '%s_')", $user)))
+ printf("[%03d] ALTER SERVER failed, [%d] %s\n", ++$test_counter,
+ mysqli_errno($link), mysqli_error($link));
+
+ if (!is_array($new_info = mysqli_get_client_stats()) || empty($new_info))
+ printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+ ++$test_counter, gettype($new_info), $new_info);
+ mysqli_get_client_stats_assert_eq('non_result_set_queries', $new_info, (string)($info['non_result_set_queries'] + 1), $test_counter, 'ALTER SERVER');
+ $info = $new_info;
+
+ if (!mysqli_query($link, "DROP SERVER myself"))
+ printf("[%03d] DROP SERVER failed, [%d] %s\n", ++$test_counter,
+ mysqli_errno($link), mysqli_error($link));
+
+ if (!is_array($new_info = mysqli_get_client_stats()) || empty($new_info))
+ printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+ ++$test_counter, gettype($new_info), $new_info);
+ mysqli_get_client_stats_assert_eq('non_result_set_queries', $new_info, (string)($info['non_result_set_queries'] + 1), $test_counter, 'DROP SERVER');
+ $info = $new_info;
+ }
+
+ mysqli_get_client_stats_assert_eq('bytes_received_real_data_normal', $info, $expected, $test_counter);
+ mysqli_get_client_stats_assert_eq('bytes_received_real_data_ps', $info, $expected, $test_counter);
+
+ /*
+ We don't test the NDB ones.
+ 13.1. Data Definition Statements
+ 13.1.3. ALTER LOGFILE GROUP Syntax
+ 13.1.4. ALTER TABLESPACE Syntax
+ 13.1.9. CREATE LOGFILE GROUP Syntax
+ 13.1.10. CREATE TABLESPACE Syntax
+ 13.1.15. DROP LOGFILE GROUP Syntax
+ 13.1.16. DROP TABLESPACE Syntax
+ */
+
+ //
+ // DML
+ //
+ if (!is_array($new_info = mysqli_get_client_stats()) || empty($new_info))
+ printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+ ++$test_counter, gettype($new_info), $new_info);
+ $info = $new_info;
+
+ if (!mysqli_query($link, "INSERT INTO test(id) VALUES (100)"))
+ printf("[%03d] INSERT failed, [%d] %s\n", ++$test_counter,
+ mysqli_errno($link), mysqli_error($link));
+
+ if (!is_array($new_info = mysqli_get_client_stats()) || empty($new_info))
+ printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+ ++$test_counter, gettype($new_info), $new_info);
+ mysqli_get_client_stats_assert_eq('non_result_set_queries', $new_info, (string)($info['non_result_set_queries'] + 1), $test_counter, 'INSERT');
+ $info = $new_info;
+
+ if (!mysqli_query($link, "UPDATE test SET label ='z' WHERE id = 100"))
+ printf("[%03d] UPDATE failed, [%d] %s\n", ++$test_counter,
+ mysqli_errno($link), mysqli_error($link));
+
+ if (!is_array($new_info = mysqli_get_client_stats()) || empty($new_info))
+ printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+ ++$test_counter, gettype($new_info), $new_info);
+ mysqli_get_client_stats_assert_eq('non_result_set_queries', $new_info, (string)($info['non_result_set_queries'] + 1), $test_counter, 'UPDATE');
+ $info = $new_info;
+
+ if (!mysqli_query($link, "REPLACE INTO test(id, label) VALUES (100, 'b')"))
+ printf("[%03d] INSERT failed, [%d] %s\n", ++$test_counter,
+ mysqli_errno($link), mysqli_error($link));
+
+ if (!is_array($new_info = mysqli_get_client_stats()) || empty($new_info))
+ printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+ ++$test_counter, gettype($new_info), $new_info);
+ mysqli_get_client_stats_assert_eq('non_result_set_queries', $new_info, (string)($info['non_result_set_queries'] + 1), $test_counter, 'REPLACE');
+ $info = $new_info;
+
+ // NOTE: this will NOT update dbl_ddls counter
+ if (!$res = mysqli_query($link, "SELECT id, label FROM test WHERE id = 100"))
+ printf("[%03d] SELECT@dml failed, [%d] %s\n", ++$test_counter,
+ mysqli_errno($link), mysqli_error($link));
+ mysqli_free_result($res);
+
+ if (!is_array($new_info = mysqli_get_client_stats()) || empty($new_info))
+ printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+ ++$test_counter, gettype($new_info), $new_info);
+ mysqli_get_client_stats_assert_eq('non_result_set_queries', $new_info, $info, $test_counter, 'SELECT@dml');
+ $info = $new_info;
+
+ if (!mysqli_query($link, "DELETE FROM test WHERE id = 100"))
+ printf("[%03d] DELETE failed, [%d] %s\n", ++$test_counter,
+ mysqli_errno($link), mysqli_error($link));
+
+ if (!is_array($new_info = mysqli_get_client_stats()) || empty($new_info))
+ printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+ ++$test_counter, gettype($new_info), $new_info);
+ mysqli_get_client_stats_assert_eq('non_result_set_queries', $new_info, (string)($info['non_result_set_queries'] + 1), $test_counter, 'DELETE');
+ $info = $new_info;
+
+ if (!$res = mysqli_query($link, "TRUNCATE TABLE test"))
+ printf("[%03d] TRUNCATE failed, [%d] %s\n", ++$test_counter,
+ mysqli_errno($link), mysqli_error($link));
+
+ if (!is_array($new_info = mysqli_get_client_stats()) || empty($new_info))
+ printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+ ++$test_counter, gettype($new_info), $new_info);
+ mysqli_get_client_stats_assert_eq('non_result_set_queries', $new_info, (string)($info['non_result_set_queries'] + 1), $test_counter, 'TRUNCATE');
+ $info = $new_info;
+
+
+ $file = tempnam(sys_get_temp_dir(), 'mysqli_test');
+ if ($fp = fopen($file, 'w')) {
+ @fwrite($fp, '1;"a"');
+ fclose($fp);
+ chmod($file, 0644);
+ $sql = sprintf('LOAD DATA LOCAL INFILE "%s" INTO TABLE test', mysqli_real_escape_string($link, $file));
+ if (mysqli_query($link, $sql)) {
+ if (!is_array($new_info = mysqli_get_client_stats()) || empty($new_info))
+ printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+ ++$test_counter, gettype($new_info), $new_info);
+ mysqli_get_client_stats_assert_eq('non_result_set_queries', $new_info, (string)($info['non_result_set_queries'] + 1), $test_counter, 'LOAD DATA LOCAL');
+ $info = $new_info;
+ }
+ unlink($file);
+ }
+
+ mysqli_get_client_stats_assert_eq('bytes_received_real_data_normal', $info, $expected, $test_counter);
+ mysqli_get_client_stats_assert_eq('bytes_received_real_data_ps', $info, $expected, $test_counter);
+
+ /*
+ We skip those:
+ 13.2. Data Manipulation Statements
+ 13.2.2. DO Syntax
+ 13.2.3. HANDLER Syntax
+ 13.2.5. LOAD DATA INFILE Syntax
+ */
+ mysqli_query($link, "DELETE FROM test");
+ if (!mysqli_query($link, "INSERT INTO test(id, label) VALUES (1, 'a'), (2, 'b')"))
+ printf("[%03d] Cannot insert new records, [%d] %s\n", ++$test_counter,
+ mysqli_errno($link), mysqli_error($link));
+
+ if (!$res = mysqli_real_query($link, "SELECT id, label FROM test ORDER BY id"))
+ printf("[%03d] Cannot SELECT with mysqli_real_query(), [%d] %s\n", ++$test_counter,
+ mysqli_errno($link), mysqli_error($link));
+
+ if (!is_object($res = mysqli_use_result($link)))
+ printf("[%03d] mysqli_use_result() failed, [%d] %s\n", ++$test_counter,
+ mysqli_errno($link), mysqli_error($link));
+
+ while ($row = mysqli_fetch_assoc($res))
+ ;
+ mysqli_free_result($res);
+ if (!is_array($new_info = mysqli_get_client_stats()) || empty($new_info))
+ printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+ ++$test_counter, gettype($new_info), $new_info);
+ mysqli_get_client_stats_assert_eq('unbuffered_sets', $new_info, (string)($info['unbuffered_sets'] + 1), $test_counter, 'mysqli_use_result()');
+ $info = $new_info;
+
+ if (!$res = mysqli_real_query($link, "SELECT id, label FROM test ORDER BY id"))
+ printf("[%03d] Cannot SELECT with mysqli_real_query() II, [%d] %s\n", ++$test_counter,
+ mysqli_errno($link), mysqli_error($link));
+
+ if (!is_object($res = mysqli_store_result($link)))
+ printf("[%03d] mysqli_use_result() failed, [%d] %s\n", ++$test_counter,
+ mysqli_errno($link), mysqli_error($link));
+
+ while ($row = mysqli_fetch_assoc($res))
+ ;
+ mysqli_free_result($res);
+ if (!is_array($new_info = mysqli_get_client_stats()) || empty($new_info))
+ printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+ ++$test_counter, gettype($new_info), $new_info);
+ mysqli_get_client_stats_assert_eq('buffered_sets', $new_info, (string)($info['buffered_sets'] + 1), $test_counter, 'mysqli_use_result()');
+ $info = $new_info;
+
+ mysqli_close($link);
+
+ mysqli_get_client_stats_assert_gt('bytes_received_real_data_normal', $info, $expected, $test_counter);
+ $expected['bytes_received_real_data_normal'] = $info['bytes_received_real_data_normal'];
+ mysqli_get_client_stats_assert_eq('bytes_received_real_data_ps', $info, $expected, $test_counter);
+
+ /*
+ no_index_used
+ bad_index_used
+ flushed_normal_sets
+ flushed_ps_sets
+ explicit_close
+ implicit_close
+ disconnect_close
+ in_middle_of_command_close
+ explicit_free_result
+ implicit_free_result
+ explicit_stmt_close
+ implicit_stmt_close
+ */
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS test"))
+ printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS non_result_set_queries_test"))
+ printf("[c003] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS client_stats_test"))
+ printf("[c004] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+if (!mysqli_query($link, "DROP DATABASE IF EXISTS mysqli_get_client_stats_"))
+ printf("[c005] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+if (!mysqli_query($link, "DROP DATABASE IF EXISTS mysqli_get_client_stats"))
+ printf("[c006] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+if (!mysqli_query($link, "DROP SERVER IF EXISTS myself"))
+ printf("[c007] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+mysqli_close($link);
+?>
+--EXPECTF--
+array(160) {
+ [%u|b%"bytes_sent"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"bytes_received"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"packets_sent"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"packets_received"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"protocol_overhead_in"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"protocol_overhead_out"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"bytes_received_ok_packet"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"bytes_received_eof_packet"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"bytes_received_rset_header_packet"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"bytes_received_rset_field_meta_packet"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"bytes_received_rset_row_packet"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"bytes_received_prepare_response_packet"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"bytes_received_change_user_packet"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"packets_sent_command"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"packets_received_ok"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"packets_received_eof"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"packets_received_rset_header"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"packets_received_rset_field_meta"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"packets_received_rset_row"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"packets_received_prepare_response"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"packets_received_change_user"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"result_set_queries"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"non_result_set_queries"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"no_index_used"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"bad_index_used"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"slow_queries"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"buffered_sets"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"unbuffered_sets"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"ps_buffered_sets"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"ps_unbuffered_sets"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"flushed_normal_sets"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"flushed_ps_sets"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"ps_prepared_never_executed"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"ps_prepared_once_executed"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"rows_fetched_from_server_normal"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"rows_fetched_from_server_ps"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"rows_buffered_from_client_normal"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"rows_buffered_from_client_ps"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"rows_fetched_from_client_normal_buffered"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"rows_fetched_from_client_normal_unbuffered"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"rows_fetched_from_client_ps_buffered"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"rows_fetched_from_client_ps_unbuffered"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"rows_fetched_from_client_ps_cursor"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"rows_affected_normal"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"rows_affected_ps"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"rows_skipped_normal"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"rows_skipped_ps"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"copy_on_write_saved"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"copy_on_write_performed"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"command_buffer_too_small"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"connect_success"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"connect_failure"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"connection_reused"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"reconnect"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"pconnect_success"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"active_connections"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"active_persistent_connections"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"explicit_close"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"implicit_close"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"disconnect_close"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"in_middle_of_command_close"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"explicit_free_result"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"implicit_free_result"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"explicit_stmt_close"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"implicit_stmt_close"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"mem_emalloc_count"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"mem_emalloc_amount"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"mem_ecalloc_count"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"mem_ecalloc_amount"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"mem_erealloc_count"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"mem_erealloc_amount"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"mem_efree_count"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"mem_efree_amount"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"mem_malloc_count"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"mem_malloc_amount"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"mem_calloc_count"]=>
+ %unicode|string%(%d) "%d"
+ [%u|b%"mem_calloc_amount"]=>
+ %unicode|string%(%d) "%d"
+ [%u|b%"mem_realloc_count"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"mem_realloc_amount"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"mem_free_count"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"mem_free_amount"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"mem_estrndup_count"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"mem_strndup_count"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"mem_estndup_count"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"mem_strdup_count"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"proto_text_fetched_null"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"proto_text_fetched_bit"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"proto_text_fetched_tinyint"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"proto_text_fetched_short"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"proto_text_fetched_int24"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"proto_text_fetched_int"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"proto_text_fetched_bigint"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"proto_text_fetched_decimal"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"proto_text_fetched_float"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"proto_text_fetched_double"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"proto_text_fetched_date"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"proto_text_fetched_year"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"proto_text_fetched_time"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"proto_text_fetched_datetime"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"proto_text_fetched_timestamp"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"proto_text_fetched_string"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"proto_text_fetched_blob"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"proto_text_fetched_enum"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"proto_text_fetched_set"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"proto_text_fetched_geometry"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"proto_text_fetched_other"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"proto_binary_fetched_null"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"proto_binary_fetched_bit"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"proto_binary_fetched_tinyint"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"proto_binary_fetched_short"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"proto_binary_fetched_int24"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"proto_binary_fetched_int"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"proto_binary_fetched_bigint"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"proto_binary_fetched_decimal"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"proto_binary_fetched_float"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"proto_binary_fetched_double"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"proto_binary_fetched_date"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"proto_binary_fetched_year"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"proto_binary_fetched_time"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"proto_binary_fetched_datetime"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"proto_binary_fetched_timestamp"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"proto_binary_fetched_string"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"proto_binary_fetched_blob"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"proto_binary_fetched_enum"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"proto_binary_fetched_set"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"proto_binary_fetched_geometry"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"proto_binary_fetched_other"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"init_command_executed_count"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"init_command_failed_count"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"com_quit"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"com_init_db"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"com_query"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"com_field_list"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"com_create_db"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"com_drop_db"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"com_refresh"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"com_shutdown"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"com_statistics"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"com_process_info"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"com_connect"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"com_process_kill"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"com_debug"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"com_ping"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"com_time"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"com_delayed_insert"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"com_change_user"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"com_binlog_dump"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"com_table_dump"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"com_connect_out"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"com_register_slave"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"com_stmt_prepare"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"com_stmt_execute"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"com_stmt_send_long_data"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"com_stmt_close"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"com_stmt_reset"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"com_stmt_set_option"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"com_stmt_fetch"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"com_deamon"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"bytes_received_real_data_normal"]=>
+ %unicode|string%(1) "0"
+ [%u|b%"bytes_received_real_data_ps"]=>
+ %unicode|string%(1) "0"
+}
+Testing buffered normal...
+Testing buffered normal... - SELECT id, label FROM test
+Testing unbuffered normal...
+Testing unbuffered normal... - SELECT id, label FROM test, not all fetched
+Testing if implicit fetching and cleaning happens...
+Testing buffered Prepared Statements...
+Testing buffered Prepared Statements... - fetching all
+Testing buffered Prepared Statements... - fetching all but one
+Testing unbuffered Prepared Statements... - fetching all
+Testing unbuffered Prepared Statements... - fetching all but one
+... done with fetch statistics
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_get_client_stats_implicit_free.phpt b/ext/mysqli/tests/mysqli_get_client_stats_implicit_free.phpt
new file mode 100644
index 0000000..880ee32
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_get_client_stats_implicit_free.phpt
@@ -0,0 +1,46 @@
+--TEST--
+mysqli_get_client_stats() - implicit_free_result
+--SKIPIF--
+<?PHP
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+if (!function_exists('mysqli_get_client_stats')) {
+ die("skip only available with mysqlnd");
+}
+?>
+--INI--
+mysqlnd.collect_statistics=1
+mysqlnd.collect_memory_statistics=1
+--FILE--
+<?php
+ require_once('connect.inc');
+ require_once('table.inc');
+
+ $stats = mysqli_get_client_stats();
+ printf("BEGINNING: implicit_free_result = %d\n", $stats['implicit_free_result']);
+
+ if (!$res = mysqli_query($link, 'SELECT id FROM test'))
+ printf("[001] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ mysqli_free_result($res);
+ mysqli_close($link);
+
+ $after = mysqli_get_client_stats();
+ if ($after['implicit_free_result'] != $stats['implicit_free_result'])
+ printf("[002] Where is the missing mysqli_free_result() call? implicit_free_result has changed by %d.\n",
+ $after['implicit_free_result'] - $stats['implicit_free_result']);
+
+ $stats = $after;
+ printf("END: implicit_free_result = %d\n", $stats['implicit_free_result']);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+BEGINNING: implicit_free_result = %d
+END: implicit_free_result = %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_get_client_stats_off.phpt b/ext/mysqli/tests/mysqli_get_client_stats_off.phpt
new file mode 100644
index 0000000..e2dff9b
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_get_client_stats_off.phpt
@@ -0,0 +1,48 @@
+--TEST--
+mysqli_get_client_stats() - php_ini setting
+--SKIPIF--
+<?PHP
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+if (!function_exists('mysqli_get_client_stats')) {
+ die("skip only available with mysqlnd");
+}
+?>
+--INI--
+mysqlnd.collect_statistics=0
+mysqlnd.collect_memory_statistics=0
+--FILE--
+<?php
+ $before = mysqli_get_client_stats();
+ if (!is_array($before) || empty($before)) {
+ printf("[001] Expecting non-empty array, got %s.\n", gettype($before));
+ var_dump($before);
+ }
+
+ // connect and table inc connect to mysql and create tables
+ require_once('connect.inc');
+ require_once('table.inc');
+ $after = mysqli_get_client_stats();
+
+ if ($before !== $after) {
+ printf("[002] Statistics have changed\n");
+ var_dump($before);
+ var_dump($after);
+ }
+
+ foreach ($after as $k => $v)
+ if ($v != 0) {
+ printf("[003] Field %s should not have any other value but 0, got %s.\n",
+ $k, $v);
+ }
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_get_client_stats_ps.phpt b/ext/mysqli/tests/mysqli_get_client_stats_ps.phpt
new file mode 100644
index 0000000..d12957b
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_get_client_stats_ps.phpt
@@ -0,0 +1,106 @@
+--TEST--
+mysqli_get_client_stats() - PS
+--SKIPIF--
+<?PHP
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+if (!function_exists('mysqli_get_client_stats')) {
+ die("skip only available with mysqlnd");
+}
+?>
+--INI--
+mysqlnd.collect_statistics=1
+mysqlnd.collect_memory_statistics=1
+--FILE--
+<?php
+ require_once('connect.inc');
+ require_once('table.inc');
+
+ $stats = mysqli_get_client_stats();
+ printf("BEGINNING: rows_fetched_from_client_ps_unbuffered = %d\n", $stats['rows_fetched_from_client_ps_unbuffered']);
+ printf("BEGINNING: rows_fetched_from_client_ps_buffered = %d\n", $stats['rows_fetched_from_client_ps_buffered']);
+ printf("BEGINNING: rows_fetched_from_client_ps_cursor = %d\n", $stats['rows_fetched_from_client_ps_cursor']);
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[001] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $id = null;
+ if (!mysqli_stmt_prepare($stmt, 'SELECT id FROM test') ||
+ !mysqli_stmt_execute($stmt) ||
+ !mysqli_stmt_store_result($stmt) ||
+ !mysqli_stmt_bind_result($stmt, $id))
+ printf("[002] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $num_rows = 0;
+ while (mysqli_stmt_fetch($stmt))
+ $num_rows++;
+
+ mysqli_stmt_free_result($stmt);
+
+ $after = mysqli_get_client_stats();
+
+ if ($after['rows_fetched_from_client_ps_unbuffered'] != $stats['rows_fetched_from_client_ps_unbuffered'])
+ printf("[003] Unbuffered rows got increased after buffered PS, expecting %d got %d.\n",
+ $stats['rows_fetched_from_client_ps_unbuffered'],
+ $after['rows_fetched_from_client_ps_unbuffered']);
+
+ $stats['rows_fetched_from_client_ps_buffered'] += $num_rows;
+ if ($after['rows_fetched_from_client_ps_buffered'] != $stats['rows_fetched_from_client_ps_buffered'] )
+ printf("[005] Buffered rows should be %d got %d.\n",
+ $stats['rows_fetched_from_client_ps_buffered'],
+ $after['rows_fetched_from_client_ps_buffered']);
+
+ $stats = $after;
+ printf("BUFFERED: rows_fetched_from_client_ps_unbuffered = %d\n", $stats['rows_fetched_from_client_ps_unbuffered']);
+ printf("BUFFERED: rows_fetched_from_client_ps_buffered = %d\n", $stats['rows_fetched_from_client_ps_buffered']);
+ printf("BUFFERED: rows_fetched_from_client_ps_cursor = %d\n", $stats['rows_fetched_from_client_ps_cursor']);
+
+ $id = null;
+ if (!mysqli_stmt_prepare($stmt, 'SELECT id FROM test') ||
+ !mysqli_stmt_execute($stmt) ||
+ !mysqli_stmt_bind_result($stmt, $id))
+ printf("[006] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $num_rows = 0;
+ while (mysqli_stmt_fetch($stmt))
+ $num_rows++;
+
+ $after = mysqli_get_client_stats();
+ $stats['rows_fetched_from_client_ps_unbuffered'] += $num_rows;
+ if ($after['rows_fetched_from_client_ps_unbuffered'] != $stats['rows_fetched_from_client_ps_unbuffered'])
+ printf("[007] Unbuffered rows should be %d got %d.\n",
+ $stats['rows_fetched_from_client_ps_unbuffered'],
+ $after['rows_fetched_from_client_ps_unbuffered']);
+
+ if ($after['rows_fetched_from_client_ps_buffered'] != $stats['rows_fetched_from_client_ps_buffered'] )
+ printf("[005] Buffered rows should be unchanged, expecting %d got %d.\n",
+ $stats['rows_fetched_from_client_ps_buffered'],
+ $after['rows_fetched_from_client_ps_buffered']);
+
+ mysqli_stmt_free_result($stmt);
+ mysqli_stmt_close($stmt);
+
+ $stats = $after;
+ printf("UNBUFFERED: rows_fetched_from_client_ps_unbuffered = %d\n", $stats['rows_fetched_from_client_ps_unbuffered']);
+ printf("UNBUFFERED: rows_fetched_from_client_ps_buffered = %d\n", $stats['rows_fetched_from_client_ps_buffered']);
+ printf("UNBUFFERED: rows_fetched_from_client_ps_cursor = %d\n", $stats['rows_fetched_from_client_ps_cursor']);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+BEGINNING: rows_fetched_from_client_ps_unbuffered = %d
+BEGINNING: rows_fetched_from_client_ps_buffered = %d
+BEGINNING: rows_fetched_from_client_ps_cursor = 0
+BUFFERED: rows_fetched_from_client_ps_unbuffered = %d
+BUFFERED: rows_fetched_from_client_ps_buffered = %d
+BUFFERED: rows_fetched_from_client_ps_cursor = 0
+UNBUFFERED: rows_fetched_from_client_ps_unbuffered = %d
+UNBUFFERED: rows_fetched_from_client_ps_buffered = %d
+UNBUFFERED: rows_fetched_from_client_ps_cursor = 0
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_get_client_stats_skipped.phpt b/ext/mysqli/tests/mysqli_get_client_stats_skipped.phpt
new file mode 100644
index 0000000..0358656
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_get_client_stats_skipped.phpt
@@ -0,0 +1,52 @@
+--TEST--
+mysqli_get_client_stats() - skipped rows
+--INI--
+mysqlnd.collect_statistics="1"
+mysqlnd.collect_memory_statistics="1"
+--SKIPIF--
+<?PHP
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+if (!function_exists('mysqli_get_client_stats')) {
+ die("skip only available with mysqlnd");
+}
+?>
+--FILE--
+<?php
+ require_once('connect.inc');
+ require_once('table.inc');
+
+ if (!$res = mysqli_query($link, 'SELECT id FROM test', MYSQLI_STORE_RESULT))
+ printf("[001] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $num_rows = mysqli_num_rows($res);
+ assert($num_rows > 2);
+ mysqli_free_result($res);
+
+ $before = mysqli_get_client_stats();
+ printf("BEFORE: rows_skipped_normal = %d\n", $before['rows_skipped_normal']);
+
+ if (!$res = mysqli_query($link, 'SELECT id FROM test', MYSQLI_USE_RESULT))
+ printf("[002] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ /* fetch all rows but the last one */
+ for ($i = 0; $i < $num_rows - 1; $i++)
+ $row = mysqli_fetch_assoc($res);
+
+ /* enforce implicit cleaning of the wire and skipping the last row */
+ mysqli_free_result($res);
+ $after = mysqli_get_client_stats();
+ printf("AFTER: rows_skipped_normal = %d\n", $after['rows_skipped_normal']);
+
+ if ($after['rows_skipped_normal'] != $before['rows_skipped_normal'] + 1)
+ printf("Statistics should show an increase of 1 for rows_skipped_normal, ".
+ "but before=%d after=%d\n", $before['rows_skipped_normal'], $after['rows_skipped_normal']);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--EXPECTF--
+BEFORE: rows_skipped_normal = %d
+AFTER: rows_skipped_normal = %d
+done!
diff --git a/ext/mysqli/tests/mysqli_get_client_version.phpt b/ext/mysqli/tests/mysqli_get_client_version.phpt
new file mode 100644
index 0000000..5862c0a
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_get_client_version.phpt
@@ -0,0 +1,14 @@
+--TEST--
+mysqli_get_client_version()
+--SKIPIF--
+<?php require_once('skipif.inc'); ?>
+<?php require_once('skipifemb.inc'); ?>
+--FILE--
+<?php
+ if (!is_int($info = mysqli_get_client_version()) || ($info < 100))
+ printf("[001] Expecting int/any_non_empty, got %s/%s\n", gettype($info), $info);
+
+ print "done!";
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_get_connection_stats.phpt b/ext/mysqli/tests/mysqli_get_connection_stats.phpt
new file mode 100644
index 0000000..64eba16
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_get_connection_stats.phpt
@@ -0,0 +1,87 @@
+--TEST--
+mysqli_get_connection_stats()
+--INI--
+mysqlnd.collect_statistics="1"
+mysqlnd.collect_memory_statistics="1"
+--SKIPIF--
+<?PHP
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+if (!function_exists('mysqli_get_connection_stats')) {
+ die("skip only available with mysqlnd");
+}
+?>
+--FILE--
+<?php
+ $tmp = $link = null;
+ if (!is_null($tmp = @mysqli_get_connection_stats()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_get_connection_stats($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require("table.inc");
+
+ if (!is_array($info = mysqli_get_connection_stats($link)) || empty($info))
+ printf("[003] Expecting array/any_non_empty, got %s/%s\n", gettype($info), $info);
+
+ if (!is_array($info2 = mysqli_get_client_stats()) || empty($info2))
+ printf("[004] Expecting array/any_non_empty, got %s/%s\n", gettype($info2), $info2);
+
+ foreach ($info as $k => &$v) {
+ if (strpos($k, "mem_") === 0) {
+ $v = 0;
+ }
+ }
+ foreach ($info2 as $k => &$v) {
+ if (strpos($k, "mem_") === 0) {
+ $v = 0;
+ }
+ }
+
+ if ($info !== $info2) {
+ printf("[005] The hashes should be identical except of the memory related fields\n");
+ var_dump($info);
+ var_dump($info2);
+ }
+
+ if (!is_array($info = $link->get_connection_stats()) || empty($info))
+ printf("[006] Expecting array/any_non_empty, got %s/%s\n", gettype($info), $info);
+
+ foreach ($info as $k => &$v) {
+ if (strpos($k, "mem_") === 0) {
+ $v = 0;
+ }
+ }
+
+ if ($info !== $info2) {
+ printf("[007] The hashes should be identical except of the memory related fields\n");
+ var_dump($info);
+ var_dump($info2);
+ }
+
+ mysqli_close($link);
+ require("table.inc");
+
+ if (!is_array($info = mysqli_get_connection_stats($link)) || empty($info))
+ printf("[008] Expecting array/any_non_empty, got %s/%s\n", gettype($info), $info);
+
+ if (!is_array($info2 = mysqli_get_client_stats()) || empty($info2))
+ printf("[009] Expecting array/any_non_empty, got %s/%s\n", gettype($info2), $info2);
+
+ // assuming the test is run in a plain-vanilla CLI environment
+ if ($info === $info2) {
+ printf("[010] The hashes should not be identical\n");
+ var_dump($info);
+ var_dump($info2);
+ }
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+done!
diff --git a/ext/mysqli/tests/mysqli_get_connection_stats_off.phpt b/ext/mysqli/tests/mysqli_get_connection_stats_off.phpt
new file mode 100644
index 0000000..4897063
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_get_connection_stats_off.phpt
@@ -0,0 +1,53 @@
+--TEST--
+mysqli_get_connection_stats() - disable via php.ini
+--INI--
+mysqlnd.collect_statistics="0"
+mysqlnd.collect_memory_statistics="0"
+--SKIPIF--
+<?PHP
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+if (!function_exists('mysqli_get_connection_stats')) {
+ die("skip only available with mysqlnd");
+}
+?>
+--FILE--
+<?php
+ // connect and table inc connect to mysql and create tables
+ require_once('connect.inc');
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ printf("[001] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+ }
+ $before = mysqli_get_connection_stats($link);
+ if (!is_array($before) || empty($before)) {
+ printf("[002] Expecting non-empty array, got %s.\n", gettype($before));
+ var_dump($before);
+ }
+
+ mysqli_close($link);
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ printf("[003] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+ }
+ $after = mysqli_get_connection_stats($link);
+
+ if ($before !== $after) {
+ printf("[004] Statistics differ!");
+ var_dump($before);
+ var_dump($after);
+ }
+
+ foreach ($after as $k => $v)
+ if ($v != 0) {
+ printf("[004] Field %s should not have any other value but 0, got %s.\n",
+ $k, $v);
+ }
+
+ mysqli_close($link);
+ print "done!";
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_get_host_info.phpt b/ext/mysqli/tests/mysqli_get_host_info.phpt
new file mode 100644
index 0000000..2c3c0f8
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_get_host_info.phpt
@@ -0,0 +1,35 @@
+--TEST--
+mysqli_get_host_info()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ if (!is_null($tmp = @mysqli_get_host_info()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_get_host_info(NULL)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require "table.inc";
+ if (!is_string($info = mysqli_get_host_info($link)) || ('' === $info))
+ printf("[003] Expecting string/any_non_empty, got %s/%s\n", gettype($info), $info);
+
+ if ($IS_MYSQLND && $host != 'localhost' && $host != '127.0.0.1' && $port != '' && $host != "" && strtoupper(substr(PHP_OS, 0, 3)) != 'WIN') {
+ /* this should be a TCP/IP connection and not a Unix Socket (or SHM or Named Pipe) */
+ if (!stristr($info, "TCP/IP"))
+ printf("[004] Should be a TCP/IP connection but mysqlnd says '%s'\n", $info);
+ }
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_get_proto_info.phpt b/ext/mysqli/tests/mysqli_get_proto_info.phpt
new file mode 100644
index 0000000..7fbefeb
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_get_proto_info.phpt
@@ -0,0 +1,29 @@
+--TEST--
+mysqli_get_proto_info()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ if (!is_null($tmp = @mysqli_get_proto_info()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_get_proto_info(NULL)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require "table.inc";
+ if (!is_int($info = mysqli_get_proto_info($link)) || ($info < 1))
+ printf("[003] Expecting int/any_non_empty, got %s/%s\n", gettype($info), $info);
+
+ if (!is_null($tmp = @mysqli_get_proto_info('too many', 'arguments')))
+ printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_get_server_info.phpt b/ext/mysqli/tests/mysqli_get_server_info.phpt
new file mode 100644
index 0000000..a7f7853
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_get_server_info.phpt
@@ -0,0 +1,33 @@
+--TEST--
+mysqli_get_server_info()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ if (!is_null($tmp = @mysqli_get_server_info()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_get_server_info(NULL)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require "table.inc";
+ if (!is_string($info = mysqli_get_server_info($link)) || ('' === $info))
+ printf("[003] Expecting string/any_non_empty, got %s/%s\n", gettype($info), $info);
+
+ if (!is_null($tmp = @mysqli_get_server_info('too', 'many arguments')))
+ printf("[005] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_get_server_version.phpt b/ext/mysqli/tests/mysqli_get_server_version.phpt
new file mode 100644
index 0000000..b30c4a3
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_get_server_version.phpt
@@ -0,0 +1,28 @@
+--TEST--
+mysqli_get_server_version()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ if (!is_null($tmp = @mysqli_get_server_version()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_get_server_version(NULL)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require "table.inc";
+ /* 5.1.5 -> 50105 -- major_version*10000 + minor_version *100 + sub_version */
+ /* < 30000 = pre 3.2.3, very unlikely! */
+ if (!is_int($info = mysqli_get_server_version($link)) || ($info < (3 * 10000)))
+ printf("[003] Expecting int/any >= 30000, got %s/%s\n", gettype($info), $info);
+
+ print "done!";
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_get_warnings.phpt b/ext/mysqli/tests/mysqli_get_warnings.phpt
new file mode 100644
index 0000000..00548de
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_get_warnings.phpt
@@ -0,0 +1,160 @@
+--TEST--
+mysqli_get_warnings() - TODO
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+require_once('connect.inc');
+if (!$TEST_EXPERIMENTAL)
+ die("skip - experimental (= unsupported) feature");
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_get_warnings()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_get_warnings($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_get_warnings('')))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ printf("[003] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+ }
+
+ if (false !== ($tmp = mysqli_get_warnings($link))) {
+ printf("[004] Expecting boolean/false, got %s/%s\n", gettype($tmp), (is_object($tmp) ? var_dump($tmp, true) : $tmp));
+ }
+
+ if (!mysqli_query($link, "DROP TABLE IF EXISTS test"))
+ printf("[005] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, "CREATE TABLE test (id SMALLINT)"))
+ printf("[006] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, "INSERT INTO test (id) VALUES (1000000)"))
+ printf("[007] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!is_object($warning = mysqli_get_warnings($link)) || 'mysqli_warning' != get_class($warning)) {
+ printf("[008] Expecting object/mysqli_warning, got %s/%s\n", gettype($tmp), (is_object($tmp) ? var_dump($tmp, true) : $tmp));
+ }
+
+ if (!method_exists($warning, 'next'))
+ printf("[009] Borked object, method next is missing\n");
+
+ $properties = array_merge(get_object_vars($warning), get_class_vars(get_class($warning)));
+ if (!empty($properties))
+ printf("[010] Properties have always been magic, hidden things - why are they visible now, a BC break...\n");
+
+ if ((!is_string($warning->message)) || ('' == $warning->message)) /* NULL or not there at all */
+ printf("[011] Expecting string/not empty, got %s/%s\n", gettype($warning->message), $warning->message);
+
+ if ((!is_string($warning->sqlstate)) || ('' == $warning->sqlstate)) /* NULL or not there at all */
+ printf("[012] Expecting string/not empty, got %s/%s\n", gettype($warning->sqlstate), $warning->sqlstate);
+
+ if ((!is_int($warning->errno)) || (0 == $warning->errno)) /* NULL or not there at all */
+ printf("[013] Expecting int/not 0, got %s/%s\n", gettype($warning->errno), $warning->errno);
+
+ if (false !== ($tmp = $warning->next()))
+ printf("[014] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_query($link, "INSERT INTO test (id) VALUES (1000000), (1000001)"))
+ printf("[015] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (($tmp = mysqli_warning_count($link)) !== 2)
+ printf("[016] Expecting 2 warnings, got %d warnings", $tmp);
+
+ if (!is_object($warning = mysqli_get_warnings($link)) || 'mysqli_warning' != get_class($warning)) {
+ printf("[017] Expecting object/mysqli_warning, got %s/%s\n", gettype($tmp), (is_object($tmp) ? var_dump($tmp, true) : $tmp));
+ }
+
+ if (true !== ($tmp = $warning->next()))
+ printf("[018] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (false !== ($tmp = $warning->next()))
+ printf("[020] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_close($link);
+
+
+ if (!$mysqli = new my_mysqli($host, $user, $passwd, $db, $port, $socket))
+ printf("[021] Cannot create mysqli object: [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+ if (!$mysqli->query("DROP TABLE IF EXISTS t1"))
+ printf("[022] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$mysqli->query("CREATE TABLE t1 (a smallint)"))
+ printf("[023] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!is_object($warning = new mysqli_warning($mysqli)))
+ printf("[024] Expecting object/mysqli_warning, got %s/%s", gettype($warning), $warning);
+
+ if (!is_string($warning->message) || ('' == $warning->message))
+ printf("[025] Expecting string, got %s/%s", gettype($warning->message), $warning->message);
+
+ if (!$mysqli->query("DROP TABLE t1"))
+ printf("[026] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ /* Yes, I really want to check if the object property is empty */
+ if (!$mysqli = new my_mysqli($host, $user, $passwd, $db, $port, $socket))
+ printf("[027] Cannot create mysqli object: [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+ $warning = new mysqli_warning($mysqli);
+ if (false !== ($tmp = $warning->next()))
+ printf("[028] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if ('' != ($tmp = $warning->message))
+ printf("[029] Expecting string/empty, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$mysqli = new my_mysqli($host, $user, $passwd, $db, $port, $socket))
+ printf("[030] Cannot create mysqli object: [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+ if (!$mysqli->query("DROP TABLE IF EXISTS t1"))
+ printf("[031] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$mysqli->query("CREATE TABLE t1 (a smallint)"))
+ printf("[032] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ /* out of range, three warnings */
+ if (!$mysqli->query("INSERT IGNORE INTO t1(a) VALUES (65536), (65536), (65536)"))
+ printf("[033] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $warning = new mysqli_warning($mysqli);
+ $i = 1;
+ while ($warning->next() && ('' != ($tmp = $warning->message))) {
+ if ((version_compare(PHP_VERSION, '5.9.9', '>') == 1) && !is_unicode($tmp))
+ printf("[033a] Warning should have been a unicode string, got %s/%s", gettype($tmp), $tmp);
+ $i++;
+ }
+ if (3 != $i)
+ printf("[034] Expecting three warnings, got %d warnings\n", $i);
+
+ $stmt = mysqli_stmt_init();
+ $warning = new mysqli_warning($stmt);
+ if (false !== ($tmp = $warning->next()))
+ printf("[035] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS test"))
+ printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS t1"))
+ printf("[c003] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+mysqli_close($link);
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_info.phpt b/ext/mysqli/tests/mysqli_info.phpt
new file mode 100644
index 0000000..2d5004f
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_info.phpt
@@ -0,0 +1,101 @@
+--TEST--
+mysqli_info()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ if (!is_null($tmp = @mysqli_info()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_info(NULL)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require "table.inc";
+ if (!$res = mysqli_query($link, "INSERT INTO test(id, label) VALUES (100, 'a')"))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ // NOTE: empty string, no multiple insert syntax
+ if (!is_string($tmp = mysqli_info($link)) || ('' != $tmp))
+ printf("[004] Expecting string/empty, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$res = mysqli_query($link, "INSERT INTO test(id, label) VALUES (101, 'a'), (102, 'b')"))
+ printf("[005] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!is_string($tmp = mysqli_info($link)) || ('' == $tmp))
+ printf("[006] Expecting string/any_non_empty, got %s/%s\n", gettype($tmp), $tmp);
+
+ if ((version_compare(PHP_VERSION, '5.9.9', '>') == 1) && !is_unicode($tmp))
+ printf("[007] Expecting unicode, because unicode mode it on. Got binary string\n");
+
+ if (!$res = mysqli_query($link, 'INSERT INTO test(id, label) SELECT id + 200, label FROM test'))
+ printf("[007] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!is_string($tmp = mysqli_info($link)) || ('' == $tmp))
+ printf("[008] Expecting string/any_non_empty, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$res = mysqli_query($link, 'ALTER TABLE test MODIFY label CHAR(2)'))
+ printf("[009] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!is_string($tmp = mysqli_info($link)) || ('' == $tmp))
+ printf("[010] Expecting string/any_non_empty, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$res = mysqli_query($link, "UPDATE test SET label = 'b' WHERE id >= 100"))
+ printf("[011] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!is_string($tmp = mysqli_info($link)) || ('' == $tmp))
+ printf("[012] Expecting string/any_non_empty, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$res = mysqli_query($link, "SELECT 1"))
+ printf("[013] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!is_string($tmp = mysqli_info($link)) || ('' != $tmp))
+ printf("[014] Expecting string/empty, got %s/%s\n", gettype($tmp), $tmp);
+ mysqli_free_result($res);
+
+ // NOTE: no LOAD DATA INFILE test
+ if ($dir = sys_get_temp_dir()) {
+ do {
+ $file = $dir . '/' . 'mysqli_info_phpt.cvs';
+ if (!$fp = fopen($file, 'w'))
+ /* ignore this error */
+ break;
+
+ if (!fwrite($fp, b"100;'a';\n") ||
+ !fwrite($fp, b"101;'b';\n") ||
+ !fwrite($fp, b"102;'c';\n")) {
+ @unlink($file);
+ break;
+ }
+ fclose($fp);
+ if (!mysqli_query($link, "DELETE FROM test")) {
+ printf("[015] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ break;
+ }
+
+ if (!@mysqli_query($link, sprintf("LOAD DATA LOCAL INFILE '%s' INTO TABLE test FIELDS TERMINATED BY ';' OPTIONALLY ENCLOSED BY '\'' LINES TERMINATED BY '\n'", $file))) {
+ /* ok, because we might not be allowed to do this */
+ @unlink($file);
+ break;
+ }
+
+ if (!is_string($tmp = mysqli_info($link)) || ('' == $tmp))
+ printf("[016] Expecting string/any_non_empty, got %s/%s\n", gettype($tmp), $tmp);
+
+ unlink($file);
+ } while (false);
+ }
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_init.phpt b/ext/mysqli/tests/mysqli_init.phpt
new file mode 100644
index 0000000..1abb7ca
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_init.phpt
@@ -0,0 +1,25 @@
+--TEST--
+mysqli_init()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ $link = mysqli_init();
+
+ if (!is_object($link) && false !== $link)
+ printf("[001] Expecting object/mysqli_link or boolean/false, got %s/%s\n", gettype($link), $link);
+
+ if (is_object($link) && 'mysqli' != get_class($link))
+ printf("[002] Expecting object of type mysqli got object of type %s\n", get_class($link));
+
+ if ($link)
+ mysqli_close($link);
+
+ print "done!";
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_insert_id.phpt b/ext/mysqli/tests/mysqli_insert_id.phpt
new file mode 100644
index 0000000..549d71d
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_insert_id.phpt
@@ -0,0 +1,140 @@
+--TEST--
+mysqli_insert_id()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_insert_id()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_insert_id($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (0 !== ($tmp = mysqli_insert_id($link)))
+ printf("[003] Expecting int/0, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$res = mysqli_query($link, "SELECT id, label FROM test ORDER BY id LIMIT 1")) {
+ printf("[004] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+ if (0 !== ($tmp = mysqli_insert_id($link)))
+ printf("[005] Expecting int/0, got %s/%s\n", gettype($tmp), $tmp);
+ mysqli_free_result($res);
+
+ // no auto_increment column
+ if (!$res = mysqli_query($link, "INSERT INTO test(id, label) VALUES (100, 'a')")) {
+ printf("[006] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+ if (0 !== ($tmp = mysqli_insert_id($link)))
+ printf("[007] Expecting int/0, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$res = mysqli_query($link, "ALTER TABLE test MODIFY id INT NOT NULL AUTO_INCREMENT")) {
+ printf("[008] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ if (!$res = mysqli_query($link, "INSERT INTO test(label) VALUES ('a')")) {
+ printf("[009] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+ if (($last_id = mysqli_insert_id($link)) <= 0)
+ printf("[010] Expecting int/any >0, got %s/%s\n", gettype($last_id), $last_id);
+
+ if (mysqli_query($link, "LOCK TABLE test WRITE")) {
+ /* we need exclusive access for a moment */
+ /* let's hope nobody changes auto_increment_increment while this code executes */
+ do {
+ if (mysqli_get_server_version($link) >= 50000) {
+ if (!$res = mysqli_query($link, 'SELECT @@auto_increment_increment AS inc')) {
+ printf("[011] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ break;
+ }
+ if (!$row = mysqli_fetch_assoc($res)) {
+ printf("[012] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ break;
+ }
+ mysqli_free_result($res);
+ $inc = $row['inc'];
+ } else {
+ $inc = 1;
+ }
+
+ if (!mysqli_query($link, "INSERT INTO test(label) VALUES ('b')")) {
+ printf("[013] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ break;
+ }
+ if (($next_id = mysqli_insert_id($link)) <= $last_id)
+ /*
+ very likely a bug, but someone could have done something on the server
+ between the second last insert and the lock, therefore don't stop just bail
+ */
+ printf("[014] Expecting int/any > %d, got %s/%s\n", $last_id, gettype($next_id), $next_id);
+
+ $last_id = $next_id;
+ if (!mysqli_query($link, "INSERT INTO test(label) VALUES ('c'), ('d'), ('e')")) {
+ printf("[015] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ break;
+ }
+ /*
+ Note: For a multiple-row insert, LAST_INSERT_ID() and mysql_insert_id() actually
+ return the AUTO_INCREMENT key from the first of the inserted rows. This allows
+ multiple-row inserts to be reproduced correctly on other servers in a replication setup.
+ */
+ if (($next_id = mysqli_insert_id($link)) != $last_id + $inc) {
+ printf("[016] Expecting int/%d, got %s/%s\n", $last_id + 1, gettype($next_id), $next_id);
+ break;
+ }
+
+ if (!$res = mysqli_query($link, "SELECT LAST_INSERT_ID() AS last_id")) {
+ printf("[017] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ break;
+ }
+ if (!$row = mysqli_fetch_assoc($res)) {
+ printf("[018] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ break;
+ }
+ mysqli_free_result($res);
+
+ if ($next_id != $row['last_id']) {
+ printf("[019] Something is wrong, check manually. Expecting %s got %s.\n",
+ $next_id, $row['last_id']);
+ break;
+ }
+ } while (false);
+ mysqli_query($link, "UNLOCK TABLE test");
+ }
+
+ if (!$res = mysqli_query($link, "INSERT INTO test(id, label) VALUES (1000, 'a')")) {
+ printf("[020] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+ if (1000 !== ($tmp = mysqli_insert_id($link)))
+ printf("[021] Expecting int/1000, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$res = mysqli_query($link, "INSERT INTO test(label) VALUES ('b'), ('c')")) {
+ printf("[022] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+ if (1000 >= ($tmp = mysqli_insert_id($link)))
+ printf("[023] Expecting int/>1000, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_close($link);
+
+ var_dump(mysqli_insert_id($link));
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Warning: mysqli_insert_id(): Couldn't fetch mysqli in %s on line %d
+NULL
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_insert_id_variation.phpt b/ext/mysqli/tests/mysqli_insert_id_variation.phpt
new file mode 100644
index 0000000..e858ca0
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_insert_id_variation.phpt
@@ -0,0 +1,103 @@
+--TEST--
+Checking last_insert_id after different operations
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+require_once("connect.inc");
+
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[001] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+$link->query("DROP TABLE IF EXISTS test_insert_id_var");
+$link->query("CREATE TABLE test_insert_id_var (id INT auto_increment, PRIMARY KEY (id))");
+$link->query("INSERT INTO test_insert_id_var VALUES (null)");
+$i = $link->insert_id;
+
+if (!$i) {
+ printf("[001] Got no valid insert id: %s", var_export($i, true));
+ die();
+}
+
+
+$link->options(MYSQLI_OPT_LOCAL_INFILE, false);
+if ($i != $link->insert_id || $i != mysqli_insert_id($link)) {
+ printf("[002] mysqli_option changes insert_id: %s", var_export($link->insert_id, true));
+ die();
+}
+
+/*
+$link->dump_debug_info();
+if ($i != $link->insert_id || $i != mysqli_insert_id($link)) {
+ printf("[003] mysqli_debug_info changes insert_id: %s", var_export($link->insert_id, true));
+ die();
+}
+*/
+
+$link->stat();
+if ($i != $link->insert_id || $i != mysqli_insert_id($link)) {
+ printf("[004] mysqli_stat changes insert_id: %s", var_export($link->insert_id, true));
+ die();
+}
+
+/*$link->kill($link->thread_id);
+if ($i != $link->insert_id || $i != mysqli_insert_id($link)) {
+ printf("[005] mysqli_kill changes insert_id: %s", var_export($link->insert_id, true));
+ die();
+}*/
+
+$link->ping();
+if ($i != $link->insert_id || $i != mysqli_insert_id($link)) {
+ printf("[006] mysqli_ping changes insert_id: %s", var_export($link->insert_id, true));
+ die();
+}
+
+/*
+mysqlnd resets the IDE to 0
+libmysql doesn't
+
+$link->change_user ($user, $passwd, $db);
+if (0 != $link->insert_id || 0 != mysqli_insert_id($link)) {
+ printf("[007] mysqli_change_user changes insert_id: %s", var_export($link->insert_id, true));
+ die();
+}
+*/
+
+$stmt = $link->prepare("SELECT 1");
+if ($i != $link->insert_id || $i != mysqli_insert_id($link)) {
+ printf("[008a] mysqli_prepare changes insert_id: %s", var_export($link->insert_id, true));
+ die();
+}
+echo mysqli_error($link);
+if (0 != $stmt->insert_id || 0 != mysqli_stmt_insert_id($stmt)) {
+ printf("[008b] mysqli_stmt doesn't initialise insert_id: %s", var_export($stmt->insert_id, true));
+ die();
+}
+
+unset($stmt);
+if ($i != $link->insert_id || $i != mysqli_insert_id($link)) {
+ printf("[009] stmt free changes insert_id: %s", var_export($link->insert_id, true));
+ die();
+}
+
+$link->query("DROP TABLE IF EXISTS test_insert_id_var");
+
+echo "DONE";
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS test_insert_id_var"))
+ printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+mysqli_close($link);
+?>
+--EXPECTF--
+DONE \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_insert_packet_overflow.phpt b/ext/mysqli/tests/mysqli_insert_packet_overflow.phpt
new file mode 100644
index 0000000..c7f38fa
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_insert_packet_overflow.phpt
@@ -0,0 +1,116 @@
+--TEST--
+INSERT and packet overflow
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ die(sprintf("SKIP [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()));
+
+$max_len = pow(2, 24);
+if (!$res = mysqli_query($link, "SHOW GLOBAL VARIABLES LIKE 'max_allowed_packet'"))
+ die(sprintf("SKIP [%d] %s\n", mysqli_errno($link), mysqli_error($link)));
+
+if (!mysqli_query($link, "SET NAMES 'latin1'"))
+ die(sprintf("SKIP [%d] %s\n", mysqli_errno($link), mysqli_error($link)));
+
+mysqli_close($link);
+?>
+--INI--
+memory_limit=256M
+--FILE--
+<?php
+ require('connect.inc');
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+ if (!$res = mysqli_query($link, "SHOW GLOBAL VARIABLES LIKE 'max_allowed_packet'"))
+ printf("[002] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$row = mysqli_fetch_assoc($res))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ mysqli_free_result($res);
+
+ if (0 === ($org_max_allowed_packet = (int)$row['Value']))
+ printf("[004] Cannot determine max_allowed_packet size and/or bogus max_allowed_packet setting used.\n");
+
+ $max_len = pow(2, 24);
+ if ($org_max_allowed_packet < $max_len) {
+ if (!mysqli_query($link, "SET GLOBAL max_allowed_packet = " . ($max_len + 100))) {
+ if (1227 == mysqli_errno($link)) {
+ /* [1227] Access denied; you need the SUPER privilege for this operation */
+ print "done!";
+ exit(0);
+ } else {
+ printf("[005] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+ }
+ }
+ mysqli_close($link);
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[006] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+ if (!mysqli_query($link, "SET NAMES 'latin1'"))
+ printf("[007] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+ if (!$res = mysqli_query($link, "SHOW GLOBAL VARIABLES LIKE 'max_allowed_packet'"))
+ printf("[008] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$row = mysqli_fetch_assoc($res))
+ printf("[009] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ mysqli_free_result($res);
+
+ if (0 === ($max_allowed_packet = (int)$row['Value']))
+ printf("[010] Cannot determine max_allowed_packet size and/or bogus max_allowed_packet setting used.\n");
+
+ $max_len = pow(2, 24);
+ if ($max_allowed_packet < $max_len) {
+ printf("[011] Failed to change max_allowed_packet");
+ }
+
+ if (!mysqli_query($link, "CREATE TABLE test(col_blob LONGBLOB) ENGINE=" . $engine))
+ printf("[012] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $query_prefix = "INSERT INTO test(col_blob) VALUES ('";
+ $query_postfix = "')";
+ $query_len = strlen($query_prefix) + strlen($query_postfix);
+ $com_query_len = 2;
+
+
+ $blob = str_repeat('a', $max_len - $com_query_len - $query_len);
+ $query = sprintf("%s%s%s", $query_prefix, $blob, $query_postfix);
+
+ if (!mysqli_query($link, $query))
+ printf("[013] max_allowed_packet = %d, strlen(query) = %d, [%d] %s\n", $max_allowed_packet, strlen($query), mysqli_errno($link), mysqli_error($link));
+
+ if (!$res = mysqli_query($link, "SELECT col_blob FROM test"))
+ printf("[014] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$row = mysqli_fetch_assoc($res)) {
+ printf("[015] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ } else {
+ if ($row['col_blob'] != $blob) {
+ printf("[016] Blob seems wrong, dumping data\n");
+ var_dump(strlen($row['col_blob']));
+ var_dump(strlen($blob));
+ }
+ mysqli_free_result($res);
+ }
+
+ if (!mysqli_query($link, "SET GLOBAL max_allowed_packet = " . $org_max_allowed_packet))
+ if (1227 != mysqli_errno($link))
+ printf("[017] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ mysqli_close($link);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_kill.phpt b/ext/mysqli/tests/mysqli_kill.phpt
new file mode 100644
index 0000000..94e4e8f
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_kill.phpt
@@ -0,0 +1,145 @@
+--TEST--
+mysqli_kill()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_kill()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_kill($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ // Zend will cast the NULL to 0
+ if (!is_bool($tmp = mysqli_kill($link, null)))
+ printf("[003] Expecting boolean/any, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$thread_id = mysqli_thread_id($link))
+ printf("[004] Cannot determine thread id, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $tmp = mysqli_kill($link, $thread_id);
+ if (!is_bool($tmp))
+ printf("[005] Expecting boolean/any, got %s/%s\n", gettype($tmp), $tmp);
+
+ if ($res = mysqli_query($link, "SELECT id FROM test LIMIT 1"))
+ pintf("[006] Expecting boolean/false, got %s/%s\n", gettype($res), $res);
+
+ var_dump($error = mysqli_error($link));
+ if (!is_string($error) || ('' === $error))
+ printf("[007] Expecting string/any non empty, got %s/%s\n", gettype($error), $error);
+ var_dump($res);
+ var_dump($link);
+ if ($IS_MYSQLND) {
+ if ($link->info != 'Records: 6 Duplicates: 0 Warnings: 0') {
+ printf("[008] mysqlnd used to be more verbose and used to support SELECT\n");
+ }
+ if ($link->stat != NULL) {
+ printf("[009] NULL expected because of error.\n");
+ }
+ } else {
+ if ($link->info != NULL) {
+ printf("[008] Time for wonders - libmysql has started to support SELECT, change test\n");
+ }
+ }
+
+ mysqli_close($link);
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[010] Cannot connect, [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+ mysqli_kill($link, -1);
+ if ((!$res = mysqli_query($link, "SELECT id FROM test LIMIT 1")) ||
+ (!$tmp = mysqli_fetch_assoc($res))) {
+ printf("[011] Connection should not be gone, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+ var_dump($tmp);
+ mysqli_free_result($res);
+ mysqli_close($link);
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[012] Cannot connect, [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+ mysqli_change_user($link, "This might work if you accept anonymous users in your setup", "password", $db); mysqli_kill($link, -1);
+
+ mysqli_close($link);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Warning: mysqli_kill(): processid should have positive value in %s on line %d
+%unicode|string%(%d) "%s"
+bool(false)
+object(mysqli)#%d (%d) {
+ [%u|b%"affected_rows"]=>
+ int(-1)
+ [%u|b%"client_info"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"client_version"]=>
+ int(%d)
+ [%u|b%"connect_errno"]=>
+ int(0)
+ [%u|b%"connect_error"]=>
+ NULL
+ [%u|b%"errno"]=>
+ int(2006)
+ [%u|b%"error"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"error_list"]=>
+ array(1) {
+ [0]=>
+ array(3) {
+ [%u|b%"errno"]=>
+ int(2006)
+ [%u|b%"sqlstate"]=>
+ %unicode|string%(5) "%s"
+ [%u|b%"error"]=>
+ %unicode|string%(%d) "%s"
+ }
+ }
+ [%u|b%"field_count"]=>
+ int(0)
+ [%u|b%"host_info"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"info"]=>
+ %s
+ [%u|b%"insert_id"]=>
+ int(0)
+ [%u|b%"server_info"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"server_version"]=>
+ int(%d)
+ [%u|b%"stat"]=>
+ %s
+ [%u|b%"sqlstate"]=>
+ %unicode|string%(5) "HY000"
+ [%u|b%"protocol_version"]=>
+ int(10)
+ [%u|b%"thread_id"]=>
+ int(%d)
+ [%u|b%"warning_count"]=>
+ int(0)
+}
+
+Warning: mysqli_kill(): processid should have positive value in %s on line %d
+array(1) {
+ [%u|b%"id"]=>
+ %unicode|string%(1) "1"
+}
+
+Warning: mysqli_kill(): processid should have positive value in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_last_insert_id.phpt b/ext/mysqli/tests/mysqli_last_insert_id.phpt
new file mode 100644
index 0000000..996c401
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_last_insert_id.phpt
@@ -0,0 +1,194 @@
+--TEST--
+API vs. SQL LAST_INSERT_ID()
+--SKIPIF--
+<?php
+ require_once('skipif.inc');
+ require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ /*
+ CAUTION: the insert_id() API call is not supposed to return
+ the same value as a call to the LAST_INSERT_ID() SQL function.
+ It is not necessarily a bug if API and SQL function return different
+ values. Check the MySQL C API reference manual for details.
+ */
+ require_once("connect.inc");
+
+ function get_sql_id($link) {
+ if (!($res = $link->query("SELECT LAST_INSERT_ID() AS _id"))) {
+ printf("[003] [%d] %s\n", $link->errno, $link->error);
+ return NULL;
+ }
+ $row = $res->fetch_assoc();
+ $res->close();
+
+ return $row['_id'];
+ }
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[001] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ if (!$link->query("DROP TABLE IF EXISTS test") ||
+ !$link->query("CREATE TABLE test (id INT auto_increment, label varchar(10) not null, PRIMARY KEY (id)) ENGINE=MyISAM") ||
+ !$link->query("INSERT INTO test (id, label) VALUES (null, 'a')")) {
+ printf("[002] [%d] %s\n", $link->errno, $link->error);
+ }
+
+ $api_id = $link->insert_id;
+ $sql_id = get_sql_id($link);
+ printf("API: %d, SQL: %d\n", $api_id, $sql_id);
+
+ if ($api_id < 1)
+ printf("[004] Expecting id > 0 got %d, [%d] %s\n", $api_id, $link->errno, $link->error) ;
+ if ($api_id != $sql_id)
+ printf("[005] SQL id %d should be equal to API id %d\n", $sql_id, $api_id);
+
+ // Not an INSERT, API value must become 0
+ if (!($res = $link->query("SELECT 1 FROM DUAL")))
+ printf("[006] [%d] %s\n", $link->errno, $link->error);
+ else
+ $res->close();
+
+ $api_id = $link->insert_id;
+ $new_sql_id = get_sql_id($link);
+ if (0 !== $api_id) {
+ printf("[007] API id should have been reset to 0 because previous query was SELECT, got API %d, SQL %d\n",
+ $api_id, $new_sql_id);
+ }
+ if ($new_sql_id != $sql_id) {
+ printf("[008] The servers LAST_INSERT_ID() changed unexpectedly from %d to %d\n", $sql_id, $new_sql_id);
+ }
+
+ // Insert fails, LAST_INSERT_ID shall not change, API shall return 0
+ if ($link->query("INSERT INTO test (id, label) VALUES (null, null)")) {
+ printf("[009] The INSERT did not fail as planned, [%d] %s\n", $link->errno, $link->error);
+ }
+ $api_id = $link->insert_id;
+ $new_sql_id = get_sql_id($link);
+
+ if (0 !== $api_id) {
+ printf("[010] API id should have been reset to 0 because previous query was SELECT, got API %d, SQL %d\n",
+ $api_id, $new_sql_id);
+ }
+ if ($new_sql_id != $sql_id) {
+ printf("[011] The servers LAST_INSERT_ID() changed unexpectedly from %d to %d\n", $sql_id, $new_sql_id);
+ }
+
+ // Sequence counter pattern...
+ if (!$link->query("UPDATE test SET id=LAST_INSERT_ID(id+1)"))
+ printf("[012] [%d] %s\n", $link->errno, $link->error);
+
+ $api_id = $link->insert_id;
+ $new_sql_id = get_sql_id($link);
+ if ($api_id < 1)
+ printf("[013] Expecting id > 0 got %d, [%d] %s\n", $api_id, $link->errno, $link->error) ;
+ if ($api_id != $new_sql_id)
+ printf("[014] SQL id %d should be equal to API id %d\n", $new_sql_id, $api_id);
+ if ($sql_id == $new_sql_id)
+ printf("[015] SQL id %d should have had changed, got %d\n", $sql_id, $new_sql_id);
+
+ $sql_id = $new_sql_id;
+
+ // Not an INSERT (after UPDATE), API value must become 0
+ if (!$link->query("SET @myvar=1"))
+ printf("[016] [%d] %s\n", $link->errno, $link->error);
+
+ $api_id = $link->insert_id;
+ $new_sql_id = get_sql_id($link);
+ if (0 !== $api_id) {
+ printf("[017] API id should have been reset to 0 because previous query was SET, got API %d, SQL %d\n",
+ $api_id, $new_sql_id);
+ }
+ if ($new_sql_id != $sql_id) {
+ printf("[018] The servers LAST_INSERT_ID() changed unexpectedly from %d to %d\n", $sql_id, $new_sql_id);
+ }
+
+ if (!$link->query("INSERT INTO test(id, label) VALUES (LAST_INSERT_ID(id + 1), 'b')"))
+ printf("[019] [%d] %s\n", $link->errno, $link->error);
+
+ $api_id = $link->insert_id;
+ $sql_id = get_sql_id($link);
+ if ($api_id != $sql_id)
+ printf("[020] SQL id %d should be equal to API id %d\n", $sql_id, $api_id);
+
+ if (!$link->query("INSERT INTO test(label) VALUES ('c')"))
+ printf("[021] [%d] %s\n", $link->errno, $link->error);
+
+ $api_id = $link->insert_id;
+ $sql_id = get_sql_id($link);
+ if ($api_id != $sql_id)
+ printf("[022] SQL id %d should be equal to API id %d\n", $sql_id, $api_id);
+
+ if (!($res = $link->query("SELECT id, label FROM test ORDER BY id ASC")))
+ printf("[023] [%d] %s\n", $link->errno, $link->error);
+
+ printf("Dumping table contents before INSERT...SELECT experiments...\n");
+ while ($row = $res->fetch_assoc()) {
+ printf("id = %d, label = '%s'\n", $row['id'], $row['label']);
+ }
+ $res->close();
+
+ if (!$link->query("INSERT INTO test(label) SELECT CONCAT(label, id) FROM test ORDER BY id ASC"))
+ printf("[024] [%d] %s\n", $link->errno, $link->error);
+
+ $api_id = $link->insert_id;
+ $sql_id = get_sql_id($link);
+ if ($api_id != $sql_id)
+ printf("[025] SQL id %d should be equal to API id %d\n", $sql_id, $api_id);
+
+ if ($link->query("INSERT INTO test(id, label) SELECT id, CONCAT(label, id) FROM test ORDER BY id ASC"))
+ printf("[026] INSERT should have failed because of duplicate PK value, [%d] %s\n", $link->errno, $link->error);
+
+ $api_id = $link->insert_id;
+ $new_sql_id = get_sql_id($link);
+ if (0 !== $api_id) {
+ printf("[027] API id should have been reset to 0 because previous query failed, got API %d, SQL %d\n",
+ $api_id, $new_sql_id);
+ }
+ if ($new_sql_id != $sql_id) {
+ printf("[028] The servers LAST_INSERT_ID() changed unexpectedly from %d to %d\n", $sql_id, $new_sql_id);
+ }
+
+ /* API insert id will be 101 because of UPDATE, SQL unchanged */
+ if (!$link->query(sprintf("INSERT INTO test(id, label) VALUES (%d, 'z') ON DUPLICATE KEY UPDATE id = 101", $sql_id) ))
+ printf("[029] [%d] %s\n", $link->errno, $link->error);
+
+ $api_id = $link->insert_id;
+ $new_sql_id = get_sql_id($link);
+ if ($api_id != 101)
+ printf("[030] API id should be %d got %d\n", $sql_id, $api_id);
+ if ($new_sql_id != $sql_id) {
+ printf("[031] The servers LAST_INSERT_ID() changed unexpectedly from %d to %d\n", $sql_id, $new_sql_id);
+ }
+
+ if (!($res = $link->query("SELECT id, label FROM test ORDER BY id ASC")))
+ printf("[032] [%d] %s\n", $link->errno, $link->error);
+
+ printf("Dumping table contents after INSERT...SELECT...\n");
+ while ($row = $res->fetch_assoc()) {
+ printf("id = %d, label = '%s'\n", $row['id'], $row['label']);
+ }
+ $res->close();
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+API: %d, SQL: %d
+Dumping table contents before INSERT...SELECT experiments...
+id = %d, label = 'b'
+id = %d, label = 'a'
+id = %d, label = 'c'
+Dumping table contents after INSERT...SELECT...
+id = %d, label = 'b'
+id = %d, label = 'a'
+id = %d, label = 'c'
+id = %d, label = 'a%d'
+id = %d, label = 'c%d'
+id = 101, label = 'b%d'
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_max_links.phpt b/ext/mysqli/tests/mysqli_max_links.phpt
new file mode 100644
index 0000000..7f49419
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_max_links.phpt
@@ -0,0 +1,76 @@
+--TEST--
+Testing mysqli.max_links
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--INI--
+mysqli.max_links=1
+--FILE--
+<?php
+ require_once("connect.inc");
+ require_once("table.inc");
+
+ // to make sure we have at least one working connection...
+ var_dump(mysqli_ping($link));
+ // to make sure that max_links is really set to one
+ var_dump((int)ini_get('mysqli.max_links'));
+
+ $links = array();
+ for ($i = 1; $i <= 5; $i++)
+ if ($links[$i] = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[%03d] One link is already open, it should not be possible to open more, [%d] %s, [%d] %s\n",
+ $i, mysqli_connect_errno(), mysqli_connect_error(),
+ mysqli_errno($links[$i]), mysqli_error($links[$i]));
+
+ for ($i = 1; $i <= 5; $i++) {
+ if ($res = mysqli_query($links[$i], 'SELECT id FROM test LIMIT 1')) {
+ printf("[%03d] Can run query on link %d\n", 5 + $i, $i);
+ mysqli_free_result($res);
+ }
+ mysqli_close($links[$i]);
+ }
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+bool(true)
+int(1)
+
+Warning: mysqli_%sonnect(): Too many open links (1) in %s on line %d
+
+Warning: mysqli_%sonnect(): Too many open links (1) in %s on line %d
+
+Warning: mysqli_%sonnect(): Too many open links (1) in %s on line %d
+
+Warning: mysqli_%sonnect(): Too many open links (1) in %s on line %d
+
+Warning: mysqli_%sonnect(): Too many open links (1) in %s on line %d
+
+Warning: mysqli_query() expects parameter 1 to be mysqli, boolean given in %s on line %d
+
+Warning: mysqli_close() expects parameter 1 to be mysqli, boolean given in %s on line %d
+
+Warning: mysqli_query() expects parameter 1 to be mysqli, boolean given in %s on line %d
+
+Warning: mysqli_close() expects parameter 1 to be mysqli, boolean given in %s on line %d
+
+Warning: mysqli_query() expects parameter 1 to be mysqli, boolean given in %s on line %d
+
+Warning: mysqli_close() expects parameter 1 to be mysqli, boolean given in %s on line %d
+
+Warning: mysqli_query() expects parameter 1 to be mysqli, boolean given in %s on line %d
+
+Warning: mysqli_close() expects parameter 1 to be mysqli, boolean given in %s on line %d
+
+Warning: mysqli_query() expects parameter 1 to be mysqli, boolean given in %s on line %d
+
+Warning: mysqli_close() expects parameter 1 to be mysqli, boolean given in %s on line %d
+done!
diff --git a/ext/mysqli/tests/mysqli_more_results.phpt b/ext/mysqli/tests/mysqli_more_results.phpt
new file mode 100644
index 0000000..271c63e
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_more_results.phpt
@@ -0,0 +1,114 @@
+--TEST--
+mysqli_more_results()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $strict_on = false;
+ if (defined('E_STRICT')) {
+ error_reporting(((int)ini_get('error_reporting')) | E_STRICT );
+ $strict_on = true;
+ }
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_more_results()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_more_results($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ print "[004]\n";
+ var_dump(mysqli_more_results($link));
+
+ if (!mysqli_multi_query($link, "SELECT 1 AS a; SELECT 1 AS a, 2 AS b; SELECT id FROM test ORDER BY id LIMIT 3"))
+ printf("[005] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ print "[006]\n";
+ $i = 1;
+
+ if ($strict_on)
+ ob_start();
+
+ if (mysqli_get_server_version($link) > 41000 && !($ret = mysqli_more_results($link)))
+ printf("[007] Expecting boolean/true, got %s/%s\n", gettype($ret), $ret);
+ do {
+ $res = mysqli_store_result($link);
+ mysqli_free_result($res);
+ if (mysqli_more_results($link))
+ printf("%d\n", $i++);
+ } while (mysqli_next_result($link));
+
+ if ($strict_on) {
+ $tmp = ob_get_contents();
+ ob_end_clean();
+ if (!preg_match('@Strict Standards: mysqli_next_result\(\): There is no next result set@ismU', $tmp)) {
+ printf("[008] Strict Standards warning missing\n");
+ } else {
+ $tmp = trim(preg_replace('@Strict Standards: mysqli_next_result\(\).*on line \d+@ism', '', $tmp));
+ }
+ print trim($tmp) . "\n";
+ }
+
+ if (!mysqli_multi_query($link, "SELECT 1 AS a; SELECT 1 AS a, 2 AS b; SELECT id FROM test ORDER BY id LIMIT 3"))
+ printf("[009] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ print "[010]\n";
+ $i = 1;
+ if (mysqli_get_server_version($link) > 41000 && !($ret = mysqli_more_results($link)))
+ printf("[011] Expecting boolean/true, got %s/%s\n", gettype($ret), $ret);
+
+ if ($strict_on)
+ ob_start();
+ do {
+ $res = mysqli_use_result($link);
+ // NOTE: if you use mysqli_use_result() with mysqli_more_results() or any other info function,
+ // you must fetch all rows before you can loop to the next result set!
+ // See also the MySQL Reference Manual: mysql_use_result()
+ while ($row = mysqli_fetch_array($res))
+ ;
+ mysqli_free_result($res);
+ if (mysqli_more_results($link))
+ printf("%d\n", $i++);
+ } while (mysqli_next_result($link));
+
+ if ($strict_on) {
+ $tmp = ob_get_contents();
+ ob_end_clean();
+ if (!preg_match('@Strict Standards: mysqli_next_result\(\): There is no next result set@ismU', $tmp)) {
+ printf("[008] Strict Standards warning missing\n");
+ } else {
+ $tmp = trim(preg_replace('@Strict Standards: mysqli_next_result\(\).*on line \d+@ism', '', $tmp));
+ }
+ print trim($tmp) . "\n";
+ }
+ mysqli_close($link);
+
+ var_dump(mysqli_more_results($link));
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+[004]
+bool(false)
+[006]
+1
+2
+[010]
+1
+2
+
+Warning: mysqli_more_results(): Couldn't fetch mysqli in %s on line %d
+NULL
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_multi_query.phpt b/ext/mysqli/tests/mysqli_multi_query.phpt
new file mode 100644
index 0000000..91c07c2
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_multi_query.phpt
@@ -0,0 +1,162 @@
+--TEST--
+mysqli_multi_query()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $strict_on = false;
+ if (defined('E_STRICT')) {
+ error_reporting(((int)ini_get('error_reporting')) | E_STRICT );
+ $strict_on = true;
+ }
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_multi_query()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_multi_query($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (false !== ($tmp = mysqli_multi_query($link, "")))
+ printf("[003] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_multi_query($link, "SELECT 1 AS a; SELECT 1 AS a, 2 AS b; SELECT id FROM test ORDER BY id LIMIT 3"))
+ printf("[005] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if ($strict_on)
+ ob_start();
+
+ $i = 0;
+ do {
+ $res = mysqli_store_result($link);
+ while ($row = mysqli_fetch_array($res))
+ ;
+ mysqli_free_result($res);
+ $i++;
+ } while (mysqli_next_result($link));
+
+ if ($strict_on) {
+ $tmp = ob_get_contents();
+ ob_end_clean();
+ if (!preg_match('@Strict Standards: mysqli_next_result\(\): There is no next result set@ismU', $tmp)) {
+ printf("[005a] Strict Standards warning missing\n");
+ } else {
+ $tmp = trim(preg_replace('@Strict Standards: mysqli_next_result\(\).*on line \d+@ism', '', $tmp));
+ }
+ print trim($tmp) . "\n";
+ }
+
+ printf("[006] %d\n", $i);
+
+ if (!mysqli_multi_query($link, "ALTER TABLE test MODIFY id INT AUTO_INCREMENT; INSERT INTO test(label) VALUES ('a'); SELECT id, label FROM test ORDER BY id"))
+ printf("[007] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $i = 0;
+ while (mysqli_next_result($link) && ($res = mysqli_store_result($link))) {
+
+ while ($row = mysqli_fetch_array($res))
+ ;
+ mysqli_free_result($res);
+ printf("%d/%d\n", $i, mysqli_insert_id($link));
+ $i++;
+ }
+ printf("[008] %d\n", $i);
+
+ if (!mysqli_multi_query($link, "SELECT id, label FROM test"))
+ printf("[009] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if ($strict_on)
+ ob_start();
+ $i = 0;
+ while (mysqli_next_result($link) && ($res = mysqli_store_result($link))) {
+ while ($row = mysqli_fetch_array($res))
+ $i++;
+ mysqli_free_result($res);
+ }
+ if ($strict_on) {
+ $tmp = ob_get_contents();
+ ob_end_clean();
+ if (!preg_match('@Strict Standards: mysqli_next_result\(\): There is no next result set@ismU', $tmp)) {
+ printf("[009a] Strict Standards warning missing\n");
+ } else {
+ $tmp = trim(preg_replace('@Strict Standards: mysqli_next_result\(\).*on line \d+@ism', '', $tmp));
+ }
+ print trim($tmp) . "\n";
+ }
+ printf("[010] %d\n", $i);
+
+ if (!mysqli_multi_query($link, "SELECT 1 AS num, 'a' AS somechar; SELECT 2 AS num, 'a' AS somechar; SELECT 3 AS num, 'a' AS somechar"))
+ printf("[011] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $res_num = 1;
+ do {
+ if (!$res = mysqli_store_result($link)) {
+ printf("[012 - %d] [%d] %s\n", $res_num, mysqli_errno($link), mysqli_error($link));
+ continue;
+ }
+
+ $num_rows = 0;
+ while ($row = mysqli_fetch_array($res)) {
+
+ $num_rows++;
+ if ($row['num'] != $res_num)
+ printf("[013 - %d] Expecting %s got %s\n", $res_num, $res_num, $row['num']);
+ if ($row['somechar'] != "a")
+ printf("[014 - %d] Expecting a got %s\n", $res_num, $row['somechar']);
+
+ if (1 == $num_rows) {
+ /* simple metadata check */
+ if (!($lengths = mysqli_fetch_lengths($res)))
+ printf("[015 - %d] [%d] %s\n", $res_num, mysqli_errno($link), mysqli_error($link));
+
+ if (count($lengths) != 2)
+ printf("[016 - %d] Expecting 2 column lengths got %d [%d] %s\n", $res_num, count($lengths));
+
+ foreach ($lengths as $k => $length)
+ if ($length <= 0)
+ printf("[017 - %d] Strange column lengths for column %d, got %d expecting any > 0\n",
+ $res_num, $k, $length);
+ }
+ }
+
+ if ($num_rows != 1)
+ printf("[018 - %d] Expecting 1 row, got %d rows\n", $num_rows);
+
+ $res_num++;
+
+ mysqli_free_result($res);
+
+ } while (@mysqli_next_result($link));
+
+ if ($res_num != 4)
+ printf("[015] Expecting 3 result sets got %d result set[s]\n", $res_num);
+
+ mysqli_close($link);
+
+ var_dump(mysqli_multi_query($link, "SELECT id, label FROM test"));
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+[006] 3
+[008] 0
+[009] [2014] Commands out of sync; you can't run this command now
+
+[010] 7
+
+Warning: mysqli_multi_query(): Couldn't fetch mysqli in %s on line %d
+NULL
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_mysqli_result_invalid_mode.phpt b/ext/mysqli/tests/mysqli_mysqli_result_invalid_mode.phpt
new file mode 100644
index 0000000..29ff657
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_mysqli_result_invalid_mode.phpt
@@ -0,0 +1,30 @@
+--TEST--
+mysqli_result(), invalid mode
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require('connect.inc');
+ require('table.inc');
+
+ $valid = array(MYSQLI_STORE_RESULT, MYSQLI_USE_RESULT);
+ do {
+ $mode = mt_rand(-1000, 1000);
+ } while (in_array($mode, $valid));
+
+ if (!is_object($res = new mysqli_result($link, $mode)))
+ printf("[001] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Warning: mysqli_result::__construct(): Invalid value for resultmode in %s on line %d
+done!
diff --git a/ext/mysqli/tests/mysqli_mysqlnd_read_timeout.phpt b/ext/mysqli/tests/mysqli_mysqlnd_read_timeout.phpt
new file mode 100644
index 0000000..67a5ab6
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_mysqlnd_read_timeout.phpt
@@ -0,0 +1,36 @@
+--TEST--
+mysqlnd.net_read_timeout limit check
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+require_once('connect.inc');
+if (!$IS_MYSQLND)
+ /* The libmysql read_timeout limit default is 365 * 24 * 3600 seconds. It cannot be altered through PHP API calls */
+ die("skip mysqlnd only test");
+?>
+--INI--
+default_socket_timeout=60
+max_execution_time=60
+mysqlnd.net_read_timeout=1
+--FILE--
+<?php
+ include ("connect.inc");
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ printf("[001] Connect failed, [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+ }
+
+ if (!$res = mysqli_query($link, "SELECT SLEEP(5)"))
+ printf("[002] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ mysqli_close($link);
+
+ print "done!";
+?>
+--EXPECTF--
+Warning: mysqli_query(): MySQL server has gone away in %s on line %d
+
+Warning: mysqli_query(): Error reading result set's header in %s on line %d
+[002] [%d] %s
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_mysqlnd_read_timeout_long.phpt b/ext/mysqli/tests/mysqli_mysqlnd_read_timeout_long.phpt
new file mode 100644
index 0000000..fcbf4e6
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_mysqlnd_read_timeout_long.phpt
@@ -0,0 +1,48 @@
+--TEST--
+mysqlnd.net_read_timeout > default_socket_timeout
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+if (!$IS_MYSQLND) {
+ die("skip: test applies only to mysqlnd");
+}
+
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ die(sprintf('skip Cannot connect to MySQL, [%d] %s.', mysqli_connect_errno(), mysqli_connect_error()));
+}
+if (mysqli_get_server_version($link) <= 50011) {
+ die(sprintf('skip Needs MySQL 5.0.12+, found version %d.', mysqli_get_server_version($link)));
+}
+?>
+--INI--
+default_socket_timeout=1
+mysqlnd.net_read_timeout=12
+max_execution_time=12
+--FILE--
+<?php
+ set_time_limit(12);
+ include ("connect.inc");
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ printf("[001] Connect failed, [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+ }
+
+ if (!$res = mysqli_query($link, "SELECT SLEEP(6)"))
+ printf("[002] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ var_dump($res->fetch_assoc());
+
+ mysqli_free_result($res);
+ mysqli_close($link);
+
+ print "done!";
+?>
+--EXPECTF--
+array(1) {
+ [%u|b%"SLEEP(6)"]=>
+ %unicode|string%(1) "0"
+}
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_mysqlnd_read_timeout_zero.phpt b/ext/mysqli/tests/mysqli_mysqlnd_read_timeout_zero.phpt
new file mode 100644
index 0000000..eb4c431
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_mysqlnd_read_timeout_zero.phpt
@@ -0,0 +1,47 @@
+--TEST--
+mysqlnd.net_read_timeout = 0
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+if (!$IS_MYSQLND) {
+ die("skip: test applies only to mysqlnd");
+}
+
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ die(sprintf('skip Cannot connect to MySQL, [%d] %s.', mysqli_connect_errno(), mysqli_connect_error()));
+}
+if (mysqli_get_server_version($link) <= 50011) {
+ die(sprintf('skip Needs MySQL 5.0.12+, found version %d.', mysqli_get_server_version($link)));
+}
+?>
+--INI--
+default_socket_timeout=10
+max_execution_time=10
+mysqlnd.net_read_timeout=0
+--FILE--
+<?php
+ include ("connect.inc");
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ printf("[001] Connect failed, [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+ }
+
+ if (!$res = mysqli_query($link, "SELECT SLEEP(2)"))
+ printf("[002] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ var_dump($res->fetch_assoc());
+
+ mysqli_free_result($res);
+ mysqli_close($link);
+
+ print "done!";
+?>
+--EXPECTF--
+array(1) {
+ [%u|b%"SLEEP(2)"]=>
+ %unicode|string%(1) "0"
+}
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_next_result.phpt b/ext/mysqli/tests/mysqli_next_result.phpt
new file mode 100644
index 0000000..c36920e
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_next_result.phpt
@@ -0,0 +1,124 @@
+--TEST--
+mysqli_next_result()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $strict_on = false;
+ if (defined('E_STRICT')) {
+ error_reporting(((int)ini_get('error_reporting')) | E_STRICT );
+ $strict_on = true;
+ }
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_next_result()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_next_result($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if ($strict_on)
+ ob_start();
+
+ if (false !== ($tmp = mysqli_next_result($link)))
+ printf("[003] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if ($strict_on) {
+ $tmp = ob_get_contents();
+ ob_end_clean();
+ if (!preg_match('@Strict Standards: mysqli_next_result\(\): There is no next result set@ismU', $tmp)) {
+ printf("[003a] Strict Standards warning missing\n");
+ } else {
+ $tmp = trim(preg_replace('@Strict Standards: mysqli_next_result\(\).*on line \d+@ism', '', $tmp));
+ }
+ print trim($tmp) . "\n";
+ ob_start();
+ }
+
+ $res = mysqli_query($link, "SELECT 1 AS res");
+ if (false !== ($tmp = mysqli_next_result($link)))
+ printf("[004] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if ($strict_on) {
+ $tmp = ob_get_contents();
+ ob_end_clean();
+ if (!preg_match('@Strict Standards: mysqli_next_result\(\): There is no next result set@ismU', $tmp)) {
+ printf("[004a] Strict Standards warning missing\n");
+ } else {
+ $tmp = trim(preg_replace('@Strict Standards: mysqli_next_result\(\).*on line \d+@ism', '', $tmp));
+ }
+ print trim($tmp) . "\n";
+ }
+
+ mysqli_free_result($res);
+
+ function func_test_mysqli_next_result($link, $query, $offset, $num_results, $strict_on) {
+
+ if (!mysqli_multi_query($link, $query))
+ printf("[%03d] [%d] %s\n", $offset, mysqli_errno($link), mysqli_error($link));
+
+ $i = 0;
+ if ($strict_on)
+ ob_start();
+
+ do {
+ if ($res = mysqli_store_result($link)) {
+ mysqli_free_result($res);
+ $i++;
+ }
+ } while (true === mysqli_next_result($link));
+
+ if ($strict_on) {
+ $tmp = ob_get_contents();
+ ob_end_clean();
+ if (!preg_match('@Strict Standards: mysqli_next_result\(\): There is no next result set@ismU', $tmp)) {
+ printf("[%03d] Strict Standards warning missing\n", $offset + 1);
+ } else {
+ $tmp = trim(preg_replace('@Strict Standards: mysqli_next_result\(\).*on line \d+@ism', '', $tmp));
+ }
+ print trim($tmp) . "\n";
+ }
+
+ if ($i !== $num_results) {
+ printf("[%03d] Expecting %d result(s), got %d result(s)\n", $offset + 2, $num_results, $i);
+ }
+
+ if (mysqli_more_results($link))
+ printf("[%03d] mysqli_more_results() indicates more results than expected\n", $offset + 3);
+
+ if (!($res = mysqli_query($link, "SELECT 1 AS b"))) {
+ printf("[%03d] [%d] %s\n", $offset + 4, mysqli_errno($link), mysqli_error($link));
+ } else {
+ mysqli_free_result($res);
+ }
+
+ }
+
+ func_test_mysqli_next_result($link, "SELECT 1 AS a; SELECT 1 AS a, 2 AS b; SELECT id FROM test ORDER BY id LIMIT 3", 5, 3, $strict_on);
+ func_test_mysqli_next_result($link, "SELECT 1 AS a; INSERT INTO test(id, label) VALUES (100, 'y'); SELECT 1 AS a, 2 AS b", 8, 2, $strict_on);
+ func_test_mysqli_next_result($link, "DELETE FROM test WHERE id >= 100; SELECT 1 AS a; ", 11, 1, $strict_on);
+
+ mysqli_close($link);
+
+ var_dump(mysqli_next_result($link));
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Warning: mysqli_next_result(): Couldn't fetch mysqli in %s on line %d
+NULL
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_no_reconnect.phpt b/ext/mysqli/tests/mysqli_no_reconnect.phpt
new file mode 100644
index 0000000..653c672
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_no_reconnect.phpt
@@ -0,0 +1,127 @@
+--TEST--
+Trying implicit reconnect after wait_timeout and KILL using mysqli_ping()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--INI--
+mysqli.reconnect=0
+--FILE--
+<?php
+ require_once("connect.inc");
+ require_once("table.inc");
+
+ if (!$link2 = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[001] Cannot create second database connection, [%d] %s\n",
+ mysqli_connect_errno(), mysqli_connect_error());
+
+ $thread_id_timeout = mysqli_thread_id($link);
+ $thread_id_control = mysqli_thread_id($link2);
+
+ if (!$res = mysqli_query($link2, "SHOW FULL PROCESSLIST"))
+ printf("[002] Cannot get full processlist, [%d] %s\n",
+ mysqli_errno($link2), mysqli_error($link));
+
+ $running_threads = array();
+ while ($row = mysqli_fetch_assoc($res))
+ $running_threads[$row['Id']] = $row;
+ mysqli_free_result($res);
+
+ if (!isset($running_threads[$thread_id_timeout]) ||
+ !isset($running_threads[$thread_id_control]))
+ printf("[003] Processlist is borked, [%d] %s\n",
+ mysqli_errno($link2), mysqli_error($link));
+
+ if (!mysqli_query($link, "SET SESSION wait_timeout = 2"))
+ printf("[004] Cannot set wait_timeout, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$res = mysqli_query($link, "SHOW VARIABLES LIKE 'wait_timeout'"))
+ printf("[005] Cannot check if wait_timeout has been set, [%d] %s\n",
+ mysqli_errno($link), mysqli_error($link));
+
+ if (!$row = mysqli_fetch_assoc($res))
+ printf("[006] Cannot get wait_timeout, [%d] %s\n",
+ mysqli_errno($link), mysqli_error($link));
+ mysqli_free_result($res);
+
+ if ($row['Value'] != 2)
+ printf("[007] Failed setting the wait_timeout, test will not work, [%d] %s\n",
+ mysqli_errno($link), mysqli_error($link));
+
+ // after 2+ seconds the server should kill the connection
+ sleep(3);
+
+ if (!$res = mysqli_query($link2, "SHOW FULL PROCESSLIST"))
+ printf("[008] Cannot get full processlist, [%d] %s\n",
+ mysqli_errno($link2), mysqli_error($link));
+
+ $running_threads = array();
+ while ($row = mysqli_fetch_assoc($res))
+ $running_threads[$row['Id']] = $row;
+ mysqli_free_result($res);
+
+ if (isset($running_threads[$thread_id_timeout]))
+ printf("[009] Server should have killed the timeout connection, [%d] %s\n",
+ mysqli_errno($link2), mysqli_error($link));
+
+ if (false !== @mysqli_ping($link))
+ printf("[010] Reconnect should not have happened");
+
+ if ($res = @mysqli_query($link, "SELECT DATABASE() as _dbname"))
+ printf("[011] Executing a query should not be possible, connection should be closed, [%d] %s\n",
+ mysqli_errno($link), mysqli_error($link));
+
+ if (!$link = @my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[012] Cannot create database connection, [%d] %s\n",
+ mysqli_connect_errno(), mysqli_connect_error());
+
+ $thread_id_timeout = mysqli_thread_id($link);
+ /*
+ Don't test for the mysqli_query() return value here.
+ It is undefined if the server replies to the query and how.
+ For example, it seems that on Linux when connecting to MySQL 5.1,
+ the server always manages to send a full a reply. Whereas MySQl 5.5
+ may not. The behaviour is undefined. Any return value is fine.
+ */
+ if ($IS_MYSQLND) {
+ /*
+ mysqlnd is a bit more verbose than libmysql. mysqlnd should print:
+ Warning: mysqli_query(): MySQL server has gone away in %s on line %d
+
+ Warning: mysqli_query(): Error reading result set's header in %d on line %d
+ */
+ @mysqli_query($link, sprintf('KILL %d', $thread_id_timeout));
+ } else {
+ mysqli_query($link, sprintf('KILL %d', $thread_id_timeout));
+ }
+ // Give the server a second to really kill the other thread...
+ sleep(1);
+
+ if (!$res = mysqli_query($link2, "SHOW FULL PROCESSLIST"))
+ printf("[014] Cannot get full processlist, [%d] %s\n",
+ mysqli_errno($link2), mysqli_error($link));
+
+ $running_threads = array();
+ while ($row = mysqli_fetch_assoc($res))
+ $running_threads[$row['Id']] = $row;
+ mysqli_free_result($res);
+
+ if (isset($running_threads[$thread_id_timeout]) ||
+ !isset($running_threads[$thread_id_control]))
+ printf("[015] Processlist is borked, [%d] %s\n",
+ mysqli_errno($link2), mysqli_error($link));
+
+ if (false !== ($tmp = @mysqli_ping($link)))
+ printf("[016] Expecting boolean/false got %s/%s\n", gettype($tmp), $tmp);
+
+ if ($res = @mysqli_query($link, "SELECT DATABASE() as _dbname"))
+ printf("[017] Running a query should not be possible, connection should be gone, [%d] %s\n",
+ mysqli_errno($link), mysqli_error($link));
+
+ mysqli_close($link2);
+ print "done!";
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_num_fields.phpt b/ext/mysqli/tests/mysqli_num_fields.phpt
new file mode 100644
index 0000000..4c2510a
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_num_fields.phpt
@@ -0,0 +1,57 @@
+--TEST--
+mysqli_num_fields()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_num_fields()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_num_fields($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ function func_test_mysqli_num_fields($link, $query, $expected, $offset, $test_free = false) {
+
+ if (!($res = mysqli_query($link, $query))) {
+ printf("[%03d] [%d] %s\n", $offset, mysqli_errno($link), mysqli_error($link));
+ return;
+ }
+
+ if ($expected !== ($tmp = mysqli_num_fields($res)))
+ printf("[%03d] Expecting %s/%d, got %s/%d\n", $offset + 1,
+ gettype($expected), $expected,
+ gettype($tmp), $tmp);
+
+ mysqli_free_result($res);
+
+ if ($test_free && (NULL !== ($tmp = mysqli_num_fields($res))))
+ printf("[%03d] Expecting NULL, got %s/%s\n", $offset + 2, gettype($tmp), $tmp);
+ }
+
+ func_test_mysqli_num_fields($link, "SELECT 1 AS a", 1, 5);
+ func_test_mysqli_num_fields($link, "SELECT id, label FROM test", 2, 10);
+ func_test_mysqli_num_fields($link, "SELECT 1 AS a, NULL AS b, 'foo' AS c", 3, 15);
+ func_test_mysqli_num_fields($link, "SELECT id FROM test", 1, 20, true);
+
+ mysqli_close($link);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Warning: mysqli_num_fields(): Couldn't fetch mysqli_result in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_num_rows.phpt b/ext/mysqli/tests/mysqli_num_rows.phpt
new file mode 100644
index 0000000..376ddd4
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_num_rows.phpt
@@ -0,0 +1,89 @@
+--TEST--
+mysqli_num_rows()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_num_rows()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_num_rows($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ function func_test_mysqli_num_rows($link, $query, $expected, $offset, $test_free = false) {
+
+ if (!$res = mysqli_query($link, $query, MYSQLI_STORE_RESULT)) {
+ printf("[%03d] [%d] %s\n", $offset, mysqli_errno($link), mysqli_error($link));
+ return;
+ }
+
+ if ($expected !== ($tmp = mysqli_num_rows($res)))
+ printf("[%03d] Expecting %s/%d, got %s/%d\n", $offset + 1,
+ gettype($expected), $expected,
+ gettype($tmp), $tmp);
+
+ mysqli_free_result($res);
+
+ if ($test_free && (NULL !== ($tmp = mysqli_num_rows($res))))
+ printf("[%03d] Expecting NULL, got %s/%s\n", $offset + 2, gettype($tmp), $tmp);
+
+ }
+
+ func_test_mysqli_num_rows($link, "SELECT 1 AS a", 1, 5);
+ func_test_mysqli_num_rows($link, "SHOW VARIABLES LIKE '%nixnutz%'", 0, 10);
+ func_test_mysqli_num_rows($link, "INSERT INTO test(id, label) VALUES (100, 'z')", NULL, 15);
+ func_test_mysqli_num_rows($link, "SELECT id FROM test LIMIT 2", 2, 20, true);
+
+ if ($res = mysqli_query($link, 'SELECT COUNT(id) AS num FROM test')) {
+
+ $row = mysqli_fetch_assoc($res);
+ mysqli_free_result($res);
+
+ func_test_mysqli_num_rows($link, "SELECT id, label FROM test", (int)$row['num'], 25);
+
+ } else {
+ printf("[030] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ print "run_tests.php don't fool me with your 'ungreedy' expression '.+?'!\n";
+
+ if ($res = mysqli_query($link, 'SELECT id FROM test', MYSQLI_USE_RESULT)) {
+
+ $row = mysqli_fetch_row($res);
+ if (0 !== ($tmp = mysqli_num_rows($res)))
+ printf("[031] Expecting int/0, got %s/%d\n", gettype($tmp), $tmp);
+
+ mysqli_free_result($res);
+
+ } else {
+ printf("[032] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Warning: mysqli_num_rows() expects parameter 1 to be mysqli_result, boolean given in %s on line %d
+
+Warning: mysqli_free_result() expects parameter 1 to be mysqli_result, boolean given in %s on line %d
+
+Warning: mysqli_num_rows(): Couldn't fetch mysqli_result in %s on line %d
+run_tests.php don't fool me with your 'ungreedy' expression '.+?'!
+
+Warning: mysqli_num_rows(): Function cannot be used with MYSQL_USE_RESULT in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_options.phpt b/ext/mysqli/tests/mysqli_options.phpt
new file mode 100644
index 0000000..2f7986d
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_options.phpt
@@ -0,0 +1,143 @@
+--TEST--
+mysqli_options()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $valid_options = array(
+ MYSQLI_READ_DEFAULT_GROUP => "MYSQLI_READ_DEFAULT_GROUP",
+ MYSQLI_READ_DEFAULT_FILE => "MYSQLI_READ_DEFAUTL_FILE",
+ MYSQLI_OPT_CONNECT_TIMEOUT => "MYSQLI_OPT_CONNECT_TIMEOUT",
+ MYSQLI_OPT_LOCAL_INFILE => "MYSQLI_OPT_LOCAL_INFILE",
+ MYSQLI_INIT_COMMAND => "MYSQLI_INIT_COMMAND",
+ MYSQLI_SET_CHARSET_NAME => "MYSQLI_SET_CHARSET_NAME",
+ MYSQLI_OPT_SSL_VERIFY_SERVER_CERT => "MYSQLI_OPT_SSL_VERIFY_SERVER_CERT",
+ );
+
+ if ($IS_MYSQLND && defined('MYSQLI_OPT_NET_CMD_BUFFER_SIZE'))
+ $valid_options[] = constant('MYSQLI_OPT_NET_CMD_BUFFER_SIZE');
+ if ($IS_MYSQLND && defined('MYSQLI_OPT_NET_READ_BUFFER_SIZE'))
+ $valid_options[] = constant('MYSQLI_OPT_NET_READ_BUFFER_SIZE');
+ if ($IS_MYSQLND && defined('MYSQLI_OPT_INT_AND_FLOAT_NATIVE'))
+ $valid_options[] = constant('MYSQLI_OPT_INT_AND_FLOAT_NATIVE');
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_options()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_options($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ $link = mysqli_init();
+
+ /* set it twice, checking if memory for the previous one is correctly freed */
+ mysqli_options($link, MYSQLI_SET_CHARSET_NAME, "utf8");
+ mysqli_options($link, MYSQLI_SET_CHARSET_NAME, "latin1");
+
+ if (!is_null($tmp = @mysqli_options($link, MYSQLI_OPT_CONNECT_TIMEOUT)))
+ printf("[003] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_options($link, "s", 'extra_my.cnf')))
+ printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_options($link, MYSQLI_INIT_COMMAND, 'SET AUTOCOMMIT=0', 'foo')))
+ printf("[005] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ // print "run_tests.php don't fool me with your 'ungreedy' expression '.+?'!\n";
+ var_dump("MYSQLI_READ_DEFAULT_GROUP", mysqli_options($link, MYSQLI_READ_DEFAULT_GROUP, 'extra_my.cnf'));
+ var_dump("MYSQLI_READ_DEFAULT_FILE", mysqli_options($link, MYSQLI_READ_DEFAULT_FILE, 'extra_my.cnf'));
+ var_dump("MYSQLI_OPT_CONNECT_TIMEOUT", mysqli_options($link, MYSQLI_OPT_CONNECT_TIMEOUT, 10));
+ var_dump("MYSQLI_OPT_LOCAL_INFILE", mysqli_options($link, MYSQLI_OPT_LOCAL_INFILE, 1));
+ var_dump("MYSQLI_INIT_COMMAND", mysqli_options($link, MYSQLI_INIT_COMMAND, array('SET AUTOCOMMIT=0', 'SET AUTOCOMMIT=1')));
+
+
+ if (!$link2 = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[006] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ if (!$res = mysqli_query($link2, 'SELECT version() AS server_version'))
+ printf("[007] [%d] %s\n", mysqli_errno($link2), mysqli_error($link2));
+ $tmp = mysqli_fetch_assoc($res);
+ mysqli_free_result($res);
+ $version = explode('.', $tmp['server_version']);
+ if (empty($version))
+ printf("[008] Cannot determine server version, need MySQL Server 4.1+ for the test!\n");
+
+ if ($version[0] <= 4 && $version[1] < 1)
+ printf("[009] Need MySQL Server 4.1+ for the test!\n");
+
+ if (!$res = mysqli_query($link2, "SHOW CHARACTER SET"))
+ printf("[010] Cannot get list of available character sets, [%d] %s\n",
+ mysqli_errno($link2), mysqli_error($link2));
+
+ $charsets = array();
+ while ($row = mysqli_fetch_assoc($res))
+ $charsets[] = $row;
+ mysqli_free_result($res);
+ mysqli_close($link2);
+
+ foreach ($charsets as $charset) {
+ $k = $charset['Charset'];
+ /* The server currently 17.07.2007 can't handle data sent in ucs2 */
+ /* The server currently 16.08.2010 can't handle data sent in utf16 and utf32 */
+ if ($charset['Charset'] == 'ucs2' || $charset['Charset'] == 'utf16' || $charset['Charset'] == 'utf32') {
+ continue;
+ }
+ if (true !== mysqli_options($link, MYSQLI_SET_CHARSET_NAME, $charset['Charset'])) {
+ printf("[009] Setting charset name '%s' has failed\n", $charset['Charset']);
+ }
+ }
+
+ var_dump("MYSQLI_READ_DEFAULT_GROUP", mysqli_options($link, MYSQLI_READ_DEFAULT_GROUP, 'extra_my.cnf'));
+ var_dump("MYSQLI_READ_DEFAULT_FILE", mysqli_options($link, MYSQLI_READ_DEFAULT_FILE, 'extra_my.cnf'));
+ var_dump("MYSQLI_OPT_CONNECT_TIMEOUT", mysqli_options($link, MYSQLI_OPT_CONNECT_TIMEOUT, 10));
+ var_dump("MYSQLI_OPT_LOCAL_INFILE", mysqli_options($link, MYSQLI_OPT_LOCAL_INFILE, 1));
+ var_dump("MYSQLI_INIT_COMMAND", mysqli_options($link, MYSQLI_INIT_COMMAND, 'SET AUTOCOMMIT=0'));
+
+ /* mysqli_real_connect() */
+ var_dump("MYSQLI_CLIENT_SSL", mysqli_options($link, MYSQLI_CLIENT_SSL, 'not a mysqli_option'));
+
+ mysqli_close($link);
+
+ echo "Link closed";
+ var_dump("MYSQLI_INIT_COMMAND", mysqli_options($link, MYSQLI_INIT_COMMAND, 'SET AUTOCOMMIT=1'));
+ print "done!";
+?>
+--EXPECTF--
+%s(25) "MYSQLI_READ_DEFAULT_GROUP"
+bool(true)
+%s(24) "MYSQLI_READ_DEFAULT_FILE"
+bool(true)
+%s(26) "MYSQLI_OPT_CONNECT_TIMEOUT"
+bool(true)
+%s(23) "MYSQLI_OPT_LOCAL_INFILE"
+bool(true)
+
+Notice: Array to string conversion in %s on line %d
+%s(19) "MYSQLI_INIT_COMMAND"
+bool(true)
+%s(25) "MYSQLI_READ_DEFAULT_GROUP"
+bool(true)
+%s(24) "MYSQLI_READ_DEFAULT_FILE"
+bool(true)
+%s(26) "MYSQLI_OPT_CONNECT_TIMEOUT"
+bool(true)
+%s(23) "MYSQLI_OPT_LOCAL_INFILE"
+bool(true)
+%s(19) "MYSQLI_INIT_COMMAND"
+bool(true)
+%s(17) "MYSQLI_CLIENT_SSL"
+bool(false)
+Link closed
+Warning: mysqli_options(): Couldn't fetch mysqli in %s line %d
+%s(19) "MYSQLI_INIT_COMMAND"
+NULL
+done!
diff --git a/ext/mysqli/tests/mysqli_options_init_command.phpt b/ext/mysqli/tests/mysqli_options_init_command.phpt
new file mode 100644
index 0000000..a78dfca
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_options_init_command.phpt
@@ -0,0 +1,78 @@
+--TEST--
+mysqli_options()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+<?php require_once('skipifemb.inc'); ?>
+--FILE--
+<?php
+ /* see mysqli.c for details */
+ require_once("connect.inc");
+
+ if (!($link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)))
+ printf("[001] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ /* TODO: test more options */
+ if (!mysqli_query($link, "DROP TABLE IF EXISTS test") ||
+ !mysqli_query($link, sprintf("CREATE TABLE test(id INT) ENGINE = %s\n", $engine)) ||
+ !mysqli_query($link, "INSERT INTO test(id) VALUES (1)"))
+ printf("[002] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$res = mysqli_query($link, "SELECT COUNT(id) AS _num_rows FROM test"))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $row = mysqli_fetch_assoc($res);
+ mysqli_free_result($res);
+
+ if ($row['_num_rows'] != 1)
+ printf("[003] Expecting 1 got %s\n", $row['_num_rows']);
+
+ mysqli_close($link);
+
+ $link = mysqli_init();
+ if (true !== mysqli_options($link, MYSQLI_INIT_COMMAND, "INSERT INTO test(id) VALUES (2)"))
+ printf("[004] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!my_mysqli_real_connect($link, $host, $user, $passwd, $db, $port, $socket))
+ printf("[005] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ if (!$res = mysqli_query($link, "SELECT COUNT(id) AS _num_rows FROM test"))
+ printf("[006] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $row = mysqli_fetch_assoc($res);
+ mysqli_free_result($res);
+
+ if ($row['_num_rows'] != 2)
+ printf("[007] Expecting 1 got %s\n", $row['_num_rows']);
+
+ mysqli_close($link);
+
+ $link = mysqli_init();
+ if (true !== mysqli_options($link, MYSQLI_INIT_COMMAND, "INSERT INTO test(i_do_no_exist) VALUES (2)"))
+ printf("[008] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ mysqli_close($link);
+
+ $link = mysqli_init();
+ if (true !== mysqli_options($link, MYSQLI_INIT_COMMAND, "INSERT INTO test(i_do_no_exist) VALUES (2)"))
+ printf("[009] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!my_mysqli_real_connect($link, $host, $user, $passwd, $db, $port, $socket))
+ printf("[010] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Warning: mysqli_real_connect(): (%s/%d): %s in %s on line %d
+[010] Cannot connect to the server using %s
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_options_int_and_float_native.phpt b/ext/mysqli/tests/mysqli_options_int_and_float_native.phpt
new file mode 100644
index 0000000..4b0c947
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_options_int_and_float_native.phpt
@@ -0,0 +1,109 @@
+--TEST--
+mysqli_options() - MYSQLI_OPT_INT_AND_FLOAT_NATIVE
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+require_once('connect.inc');
+if (!$IS_MYSQLND)
+ die("skip mysqlnd only test");
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+
+ $types = array(
+ 'BIT' => array('BIT(8)', 0),
+ 'TINYINT' => array('TINYINT', 120),
+ 'BOOL' => array('BOOL', 0),
+ 'BOOLEAN' => array('BOOLEAN', 1),
+ 'SMALLINT' => array('SMALLINT', 32000),
+ 'MEDIUMINT' => array('MEDIUMINT', 999),
+ 'INT' => array('INT', 999),
+ 'BIGINT' => array('BIGINT', 999),
+ 'FLOAT' => array('FLOAT', 1.3),
+ 'DOUBLE' => array('DOUBLE', -1.3),
+ );
+
+ foreach ($types as $name => $data) {
+ $link = mysqli_init();
+ if (!mysqli_options($link, MYSQLI_OPT_INT_AND_FLOAT_NATIVE, 1)) {
+ printf("[001] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ continue;
+ }
+
+ if (!my_mysqli_real_connect($link, $host, $user, $passwd, $db, $port, $socket)) {
+ printf("[002] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+ continue;
+ }
+
+
+ if (!mysqli_query($link, "DROP TABLE IF EXISTS test")) {
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ continue;
+ }
+
+ if (!mysqli_query($link, sprintf("CREATE TABLE test (id %s)", $data[0]))) {
+ printf("[004] TODO [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ continue;
+ }
+
+ if (!mysqli_query($link, sprintf("INSERT INTO test(id) VALUES (%f)", $data[1]))) {
+ printf("[005] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ continue;
+ }
+
+ if (!$res = mysqli_query($link, "SELECT id FROM test")) {
+ printf("[006] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ continue;
+ }
+
+ $row = mysqli_fetch_assoc($res);
+ mysqli_free_result($res);
+
+ if ($row['id'] !== $data[1]) {
+ printf("[007] Expecting %s - %s/%s got %s/%s\n",
+ $name,
+ $data[1], gettype($data[1]), $row['id'], gettype($row['id']));
+ }
+ mysqli_close($link);
+
+ $link = mysqli_init();
+ if (!mysqli_options($link, MYSQLI_OPT_INT_AND_FLOAT_NATIVE, 0)) {
+ printf("[008] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ continue;
+ }
+
+ if (!my_mysqli_real_connect($link, $host, $user, $passwd, $db, $port, $socket)) {
+ printf("[009] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+ continue;
+ }
+
+ if (!$res = mysqli_query($link, "SELECT id FROM test")) {
+ printf("[010] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ continue;
+ }
+
+ $row = mysqli_fetch_assoc($res);
+ mysqli_free_result($res);
+
+ if (!is_string($row['id']) || ($row['id'] != $data[1])) {
+ printf("[011] Expecting %s - %s/string got %s/%s\n",
+ $name,
+ $data[1], $row['id'], gettype($row['id']));
+ }
+ mysqli_close($link);
+
+ }
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_options_openbasedir.phpt b/ext/mysqli/tests/mysqli_options_openbasedir.phpt
new file mode 100644
index 0000000..4c13ec1
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_options_openbasedir.phpt
@@ -0,0 +1,23 @@
+--TEST--
+mysqli_options() - MYSQLI_OPT_LOCAL_INFILE and open_basedir
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once('connect.inc');
+ ini_set("open_basedir", __DIR__);
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[001] Cannot connect, [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+ if (false !== mysqli_options($link, MYSQLI_OPT_LOCAL_INFILE, 1))
+ printf("[002] Can set MYSQLI_OPT_LOCAL_INFILE although open_basedir is set!\n");
+
+ mysqli_close($link);
+ print "done!";
+?>
+--EXPECTF--
+done!
diff --git a/ext/mysqli/tests/mysqli_pconn_conn_multiple.phpt b/ext/mysqli/tests/mysqli_pconn_conn_multiple.phpt
new file mode 100644
index 0000000..adc2671
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_pconn_conn_multiple.phpt
@@ -0,0 +1,161 @@
+--TEST--
+Calling connect() on an open persistent connection to create a new persistent connection
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--INI--
+mysqli.allow_persistent=1
+mysqli.max_persistent=-1
+mysqli.max_links=-1
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $phost = 'p:' . $host;
+
+ if (!$link = my_mysqli_connect($phost, $user, $passwd, $db, $port, $socket))
+ printf("[001] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $phost, $user, $db, $port, $socket);
+
+ if (!$thread_id = $link->thread_id)
+ printf("[002] Cannot determine thread id, test will fail, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (true !== ($tmp = my_mysqli_real_connect($link, $host, $user, $passwd, $db, $port, $socket)))
+ printf("[003] Expecting boolean/true got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_int($new_thread_id = mysqli_thread_id($link)) || ($new_thread_id < 0))
+ printf("[004] Expecting int/any got %s/%s\n", gettype($tmp), $tmp);
+
+ if ($thread_id == $new_thread_id)
+ printf("[005] Expecting new connection and new thread id. Old thread id %d, new thread id %d\n", $thread_id, $new_thread_id);
+
+ if (!($res = mysqli_query($link, "SELECT 'ok' AS it_works")) ||
+ !($row = mysqli_fetch_assoc($res)))
+ printf("[006] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ var_dump($row);
+ mysqli_free_result($res);
+
+ mysqli_close($link);
+
+ if (!$link = new my_mysqli($phost, $user, $passwd, $db, $port, $socket))
+ printf("[007] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $phost, $user, $db, $port, $socket);
+
+ if (!$thread_id = $link->thread_id)
+ printf("[008] Cannot determine thread id, test will fail, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (true !== ($tmp = $link->real_connect($host, $user, $passwd, $db, $port, $socket)))
+ printf("[009] Expecting boolean/true got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_int($new_thread_id = $link->thread_id) || ($new_thread_id < 0))
+ printf("[010] Expecting int/any got %s/%s\n", gettype($tmp), $tmp);
+
+ if ($thread_id == $new_thread_id)
+ printf("[011] Expecting new connection and new thread id. Old thread id %d, new thread id %d\n", $thread_id, $new_thread_id);
+
+ if (!($res = $link->query("SELECT 'works also with oo' AS syntax")) ||
+ !($row = $res->fetch_assoc()))
+ printf("[012] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ var_dump($row);
+ mysqli_free_result($res);
+
+ mysqli_close($link);
+
+ if (NULL !== ($tmp = $link->connect($phost, $user, $passwd, $db, $port, $socket)))
+ printf("[013] Expecting NULL got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$link = mysqli_connect($phost, $user, $passwd, $db, $port, $socket))
+ printf("[014] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $phost, $user, $db, $port, $socket);
+
+ if (NULL !== ($tmp = $link->connect($host, $user, $passwd, $db, $port, $socket)))
+ printf("[015] Expecting NULL got %s/%s\n", gettype($tmp), $tmp);
+
+ printf("Flipping phost/host order\n");
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[016] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ if (!$thread_id = mysqli_thread_id($link))
+ printf("[017] Cannot determine thread id, test will fail, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (true !== ($tmp = my_mysqli_real_connect($link, $phost, $user, $passwd, $db, $port, $socket)))
+ printf("[018] Expecting boolean/true got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_int($new_thread_id = mysqli_thread_id($link)) || ($new_thread_id < 0))
+ printf("[019] Expecting int/any got %s/%s\n", gettype($tmp), $tmp);
+
+ if ($thread_id == $new_thread_id)
+ printf("[020] Expecting new connection and new thread id. Old thread id %d, new thread id %d\n", $thread_id, $new_thread_id);
+
+ if (!($res = mysqli_query($link, "SELECT 'ok' AS it_works")) ||
+ !($row = mysqli_fetch_assoc($res)))
+ printf("[021] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ var_dump($row);
+ mysqli_free_result($res);
+
+ mysqli_close($link);
+
+ if (!$link = new my_mysqli($host, $user, $passwd, $db, $port, $socket))
+ printf("[022] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ if (!$thread_id = $link->thread_id)
+ printf("[023] Cannot determine thread id, test will fail, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (true !== ($tmp = $link->real_connect($phost, $user, $passwd, $db, $port, $socket)))
+ printf("[024] Expecting boolean/true got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_int($new_thread_id = $link->thread_id) || ($new_thread_id < 0))
+ printf("[025] Expecting int/any got %s/%s\n", gettype($tmp), $tmp);
+
+ if ($thread_id == $new_thread_id)
+ printf("[026] Expecting new connection and new thread id. Old thread id %d, new thread id %d\n", $thread_id, $new_thread_id);
+
+ if (!($res = $link->query("SELECT 'works also with oo' AS syntax")) ||
+ !($row = $res->fetch_assoc()))
+ printf("[027] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ var_dump($row);
+ mysqli_free_result($res);
+
+ mysqli_close($link);
+
+ if (NULL !== ($tmp = $link->connect($host, $user, $passwd, $db, $port, $socket)))
+ printf("[028] Expecting NULL got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[029] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ if (NULL !== ($tmp = $link->connect($phost, $user, $passwd, $db, $port, $socket)))
+ printf("[030] Expecting NULL got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--EXPECTF--
+array(1) {
+ [%u|b%"it_works"]=>
+ %unicode|string%(2) "ok"
+}
+array(1) {
+ [%u|b%"syntax"]=>
+ %unicode|string%(18) "works also with oo"
+}
+Flipping phost/host order
+array(1) {
+ [%u|b%"it_works"]=>
+ %unicode|string%(2) "ok"
+}
+array(1) {
+ [%u|b%"syntax"]=>
+ %unicode|string%(18) "works also with oo"
+}
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_pconn_disabled.phpt b/ext/mysqli/tests/mysqli_pconn_disabled.phpt
new file mode 100644
index 0000000..7222212
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_pconn_disabled.phpt
@@ -0,0 +1,62 @@
+--TEST--
+mysqli_pconnect() - mysqli.allow_persistent = 0
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+die("skip TODO - we need to add a user level way to check if CHANGE_USER gets called by pconnect");
+?>
+--INI--
+mysqli.allow_persistent=0
+mysqli.max_persistent=2
+mysqli.max_links=2
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $host = 'p:' . $host;
+ if (!$link1 = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ // automatic downgrade to normal connections has failed
+ printf("[001] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s, [%d] %s\n",
+ $host, $user, $db, $port, $socket, mysqli_connect_errno(), mysqli_connect_error());
+ }
+ if (!mysqli_query($link1, "SET @pcondisabled = 'Connection 1'"))
+ printf("[002] Cannot set user variable to check if we got the same persistent connection, [%d] %s\n",
+ mysqli_errno($link1), mysqli_error($link1));
+
+ if (!$link2 = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ // automatic downgrade to normal connections has failed
+ printf("[003] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s, [%d] %s\n",
+ $host, $user, $db, $port, $socket, mysqli_connect_errno(), mysqli_connect_error());
+ }
+
+ if (!$res = mysqli_query($link1, 'SELECT @pcondisabled AS _test'))
+ printf("[004] [%d] %s\n", mysqli_errno($link2), mysqli_error($link2));
+
+ $row = mysqli_fetch_assoc($res);
+ printf("Connecction 1 - SELECT @pcondisabled -> '%s'\n", $row['_test']);
+ mysqli_free_result($res);
+
+ if (!$res = mysqli_query($link2, 'SELECT @pcondisabled AS _test'))
+ printf("[005] [%d] %s\n", mysqli_errno($link2), mysqli_error($link2));
+
+ $row = mysqli_fetch_assoc($res);
+ printf("Connecction 2 - SELECT @pcondisabled -> '%s'\n", $row['_test']);
+ mysqli_free_result($res);
+
+ if ($link1 === $link2)
+ printf("[006] Links should not be identical\n");
+
+ mysqli_close($link1);
+ mysqli_close($link2);
+ print "done!";
+?>
+--EXPECTF--
+Warning: my_mysqli_connect(): Persistent connections are disabled. Downgrading to normal in %s on line %d
+
+Warning: my_mysqli_connect(): Persistent connections are disabled. Downgrading to normal in %s on line %d
+Connecction 1 - SELECT @pcondisabled -> 'Connection 1'
+Connecction 2 - SELECT @pcondisabled -> ''
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_pconn_kill.phpt b/ext/mysqli/tests/mysqli_pconn_kill.phpt
new file mode 100644
index 0000000..f8d8d7e
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_pconn_kill.phpt
@@ -0,0 +1,95 @@
+--TEST--
+Killing a persistent connection.
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+require_once("connect.inc");
+?>
+--INI--
+mysqli.allow_persistent=1
+mysqli.max_persistent=2
+--FILE--
+<?php
+ require_once("connect.inc");
+ require_once("table.inc");
+
+ $host = 'p:' . $host;
+ if (!$plink = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[001] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ // get the thread ids of the two connections...
+ $thread_id = mysqli_thread_id($link);
+ $pthread_id = mysqli_thread_id($plink);
+
+ if (!$res = mysqli_query($link, 'SHOW FULL PROCESSLIST'))
+ printf("[002] Cannot get processlist, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $running_threads = array();
+ while ($row = mysqli_fetch_assoc($res))
+ $running_threads[$row['Id']] = $row;
+ mysqli_free_result($res);
+
+ if (count($running_threads) < 2)
+ printf("[003] Processlist is too short, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!isset($running_threads[$thread_id]))
+ printf("[004] Cannot find thread id of the regular link, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!isset($running_threads[$pthread_id]))
+ printf("[005] Cannot find thread id of the persistent link, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ // Kill the persistent connection - don't use mysqli_kill, mysqlnd will catch that...
+ if (!mysqli_query($link, sprintf('KILL %d', $pthread_id)))
+ printf("[006] Cannot kill persistent connection, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ mysqli_close($plink);
+ // Give the server think-time to kill the pthread
+ sleep(1);
+
+ if (!$res = mysqli_query($link, 'SHOW FULL PROCESSLIST'))
+ printf("[007] Cannot get processlist, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $running_threads2 = array();
+ while ($row = mysqli_fetch_assoc($res))
+ $running_threads2[$row['Id']] = $row;
+ mysqli_free_result($res);
+
+ if (isset($running_threads2[$pthread_id]))
+ printf("[008] Thread of the persistent connection should have been gone, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ if (!isset($running_threads2[$thread_id]))
+ printf("[009] Thread of the regular connection should be still there, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ // On PHP side this should do nothing. PHP should not try to close the connection or something.
+ @mysqli_close($plink);
+
+ if (!$plink = @my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[011] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+ if (!$res3 = @mysqli_query($plink, 'SELECT id FROM test ORDER BY id LIMIT 1')) {
+ printf("[012] New persistent connection cannot execute queries, [%d] %s\n", @mysqli_errno($plink), @mysqli_error($plink));
+ }
+
+ @mysqli_free_result($res3);
+ @mysqli_close($plink);
+ mysqli_close($link);
+
+ // remove the "p:<host>" from the host variable
+ $host = substr($host, 2);
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[013] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+ if (!$res4 = mysqli_query($link, 'SELECT id FROM test ORDER BY id LIMIT 1'))
+ printf("[014] New regular connection cannot execute queries, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ mysqli_free_result($res4);
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_pconn_limits.phpt b/ext/mysqli/tests/mysqli_pconn_limits.phpt
new file mode 100644
index 0000000..ee9e1f9
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_pconn_limits.phpt
@@ -0,0 +1,98 @@
+--TEST--
+Persistent connections - limits (-1, unlimited)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+require_once("connect.inc");
+?>
+--INI--
+mysqli.allow_persistent=1
+mysqli.max_persistent=-1
+mysqli.max_links=-1
+--FILE--
+<?php
+ require_once("connect.inc");
+ // opens a regular connection
+ require_once("table.inc");
+
+ if (!$res = mysqli_query($link, "SELECT 'works..' as _desc"))
+ printf("[001] Cannot run query, [%d] %s\n",
+ mysqli_errno($link), mysqli_error($link));
+
+ $row = mysqli_fetch_assoc($res);
+ mysqli_free_result($res);
+ printf("Regular connection 1 - '%s'\n", $row['_desc']);
+
+ if (!$link2 = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[002] Cannot open second regular connection, [%d] %s\n",
+ mysqli_connect_errno(), mysqli_connect_error());
+
+ if (!$res = mysqli_query($link2, "SELECT 'works...' as _desc"))
+ printf("[003] Cannot run query, [%d] %s\n",
+ mysqli_errno($link2), mysqli_error($link2));
+
+ $row = mysqli_fetch_assoc($res);
+ mysqli_free_result($res);
+ printf("Regular connection 2 - '%s'\n", $row['_desc']);
+
+ $host = 'p:' . $host;
+ if (!$plink = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[004] Cannot create persistent connection using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s, [%d] %s\n",
+ $host, $user, $db, $port, $socket,
+ mysqli_connect_errno(), mysqli_connect_error());
+
+ if (!$res = mysqli_query($plink, "SELECT 'works...' as _desc"))
+ printf("[005] Cannot run query, [%d] %s\n",
+ mysqli_errno($plink), mysqli_error($plink));
+
+ $row = mysqli_fetch_assoc($res);
+ mysqli_free_result($res);
+ printf("Persistent connection 1 - '%s'\n", $row['_desc']);
+
+ if (!$plink2 = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[006] Cannot create persistent connection using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s, [%d] %s\n",
+ $host, $user, $db, $port, $socket,
+ mysqli_connect_errno(), mysqli_connect_error());
+
+ if (!$res = mysqli_query($plink2, "SELECT 'works...' as _desc"))
+ printf("[007] Cannot run query, [%d] %s\n",
+ mysqli_errno($plink2), mysqli_error($plink2));
+
+ $row = mysqli_fetch_assoc($res);
+ mysqli_free_result($res);
+ printf("Persistent connection 2 - '%s'\n", $row['_desc']);
+
+ $plink3 = mysqli_init();
+ if (!my_mysqli_real_connect($plink3, $host, $user, $passwd, $db, $port, $socket))
+ printf("[008] Cannot create persistent connection using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s, [%d] %s\n",
+ $host, $user, $db, $port, $socket,
+ mysqli_connect_errno(), mysqli_connect_error());
+
+ if (!$res = mysqli_query($plink3, "SELECT 'works...' as _desc"))
+ printf("[009] Cannot run query, [%d] %s\n",
+ mysqli_errno($plink2), mysqli_error($plink2));
+
+ $row = mysqli_fetch_assoc($res);
+ mysqli_free_result($res);
+ printf("Persistent connection 3 - '%s'\n", $row['_desc']);
+
+ mysqli_close($link);
+ mysqli_close($link2);
+ mysqli_close($plink);
+ mysqli_close($plink2);
+ mysqli_close($plink3);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Regular connection 1 - 'works..'
+Regular connection 2 - 'works...'
+Persistent connection 1 - 'works...'
+Persistent connection 2 - 'works...'
+Persistent connection 3 - 'works...'
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_pconn_max_links.phpt b/ext/mysqli/tests/mysqli_pconn_max_links.phpt
new file mode 100644
index 0000000..e87ef00
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_pconn_max_links.phpt
@@ -0,0 +1,196 @@
+--TEST--
+Persistent connections and mysqli.max_links
+--SKIPIF--
+<?php
+ require_once('skipif.inc');
+ require_once('skipifemb.inc');
+ require_once('skipifconnectfailure.inc');
+ require_once('table.inc');
+
+ mysqli_query($link, 'DROP USER pcontest');
+ mysqli_query($link, 'DROP USER pcontest@localhost');
+
+ if (!mysqli_query($link, 'CREATE USER pcontest@"%" IDENTIFIED BY "pcontest"') ||
+ !mysqli_query($link, 'CREATE USER pcontest@localhost IDENTIFIED BY "pcontest"')) {
+ printf("skip Cannot create second DB user [%d] %s", mysqli_errno($link), mysqli_error($link));
+ mysqli_close($link);
+ die("skip CREATE USER failed");
+ }
+
+ // we might be able to specify the host using CURRENT_USER(), but...
+ if (!mysqli_query($link, sprintf("GRANT SELECT ON TABLE %s.test TO pcontest@'%%'", $db)) ||
+ !mysqli_query($link, sprintf("GRANT SELECT ON TABLE %s.test TO pcontest@'localhost'", $db))) {
+ printf("skip Cannot GRANT SELECT to second DB user [%d] %s", mysqli_errno($link), mysqli_error($link));
+ mysqli_query($link, 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM pcontest');
+ mysqli_query($link, 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM pcontest@localhost');
+ mysqli_query($link, 'DROP USER pcontest@localhost');
+ mysqli_query($link, 'DROP USER pcontest');
+ mysqli_close($link);
+ die("skip GRANT failed");
+ }
+
+ if (!($link_pcontest = @my_mysqli_connect($host, 'pcontest', 'pcontest', $db, $port, $socket))) {
+ mysqli_query($link, 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM pcontest');
+ mysqli_query($link, 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM pcontest@localhost');
+ mysqli_query($link, 'DROP USER pcontest@localhost');
+ mysqli_query($link, 'DROP USER pcontest');
+ mysqli_close($link);
+ die("skip CONNECT using new user failed");
+ }
+ mysqli_close($link);
+?>
+--INI--
+mysqli.allow_persistent=1
+mysqli.max_persistent=2
+--FILE--
+<?php
+ require_once("connect.inc");
+ require_once('table.inc');
+
+
+ if (!mysqli_query($link, 'DROP USER pcontest') ||
+ !mysqli_query($link, 'DROP USER pcontest@localhost') ||
+ !mysqli_query($link, 'CREATE USER pcontest@"%" IDENTIFIED BY "pcontest"') ||
+ !mysqli_query($link, 'CREATE USER pcontest@localhost IDENTIFIED BY "pcontest"') ||
+ !mysqli_query($link, sprintf("GRANT SELECT ON TABLE %s.test TO pcontest@'%%'", $db)) ||
+ !mysqli_query($link, sprintf("GRANT SELECT ON TABLE %s.test TO pcontest@'localhost'", $db))) {
+ printf("[000] Init failed, [%d] %s\n",
+ mysqli_errno($plink), mysqli_error($plink));
+ }
+
+ if (!$plink = my_mysqli_connect('p:' . $host, 'pcontest', 'pcontest', $db, $port, $socket))
+ printf("[001] Cannot connect using the second DB user created during SKIPIF, [%d] %s\n",
+ mysqli_connect_errno(), mysqli_connect_error());
+
+ ob_start();
+ phpinfo();
+ $phpinfo = strip_tags(ob_get_contents());
+ ob_end_clean();
+
+ $phpinfo = substr($phpinfo, strpos($phpinfo, 'MysqlI Support => enabled'), 500);
+ if (!preg_match('@Active Persistent Links\s+=>\s+(\d+)@ismU', $phpinfo, $matches))
+ printf("[002] Cannot get # active persistent links from phpinfo()\n");
+ $num_plinks = $matches[1];
+
+ if (!$res = mysqli_query($plink, 'SELECT id, label FROM test WHERE id = 1'))
+ printf("[003] Cannot run query on persistent connection of second DB user, [%d] %s\n",
+ mysqli_errno($plink), mysqli_error($plink));
+
+ if (!$row = mysqli_fetch_assoc($res))
+ printf("[004] Cannot run fetch result, [%d] %s\n",
+ mysqli_errno($plink), mysqli_error($plink));
+ mysqli_free_result($res);
+ var_dump($row);
+
+ // change the password for the second DB user and kill the persistent connection
+ if (!mysqli_query($link, 'SET PASSWORD FOR pcontest = PASSWORD("newpass")') ||
+ !mysqli_query($link, 'FLUSH PRIVILEGES'))
+ printf("[005] Cannot change PW of second DB user, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ // change the password for the second DB user and kill the persistent connection
+ if (!mysqli_query($link, 'SET PASSWORD FOR pcontest@localhost = PASSWORD("newpass")') ||
+ !mysqli_query($link, 'FLUSH PRIVILEGES'))
+ printf("[006] Cannot change PW of second DB user, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ // persistent connections cannot be closed but only be killed
+ $pthread_id = mysqli_thread_id($plink);
+ if (!mysqli_query($link, sprintf('KILL %d', $pthread_id)))
+ printf("[007] Cannot KILL persistent connection of second DB user, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ // give the server a second to really kill the thread
+ sleep(1);
+
+ if (!$res = mysqli_query($link, "SHOW FULL PROCESSLIST"))
+ printf("[008] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $running_threads = array();
+ while ($row = mysqli_fetch_assoc($res))
+ $running_threads[$row['Id']] = $row;
+ mysqli_free_result($res);
+
+ if (isset($running_threads[$pthread_id]))
+ printf("[009] Persistent connection has not been killed\n");
+
+ // this fails and we have 0 (<= $num_plinks) connections
+ if ($plink = @my_mysqli_connect('p:' . $host, 'pcontest', 'pcontest', $db, $port, $socket))
+ printf("[010] Can connect using the old password, [%d] %s\n",
+ mysqli_connect_errno($link), mysqli_connect_error($link));
+
+ ob_start();
+ phpinfo();
+ $phpinfo = strip_tags(ob_get_contents());
+ ob_end_clean();
+ $phpinfo = substr($phpinfo, stripos($phpinfo, 'MysqlI Support => enabled'), 500);
+ if (!preg_match('@Active Persistent Links\s+=>\s+(\d+)@ismU', $phpinfo, $matches))
+ printf("[010] Cannot get # of active persistent links from phpinfo()\n");
+
+ $num_plinks_kill = $matches[1];
+ if ($num_plinks_kill > $num_plinks)
+ printf("[011] Expecting Active Persistent Links < %d, got %d\n", $num_plinks, $num_plinks_kill);
+
+ if (!$plink = my_mysqli_connect('p:' . $host, 'pcontest', 'newpass', $db, $port, $socket))
+ printf("[012] Cannot connect using the new password, [%d] %s\n",
+ mysqli_connect_errno(), mysqli_connect_error());
+
+ if (!$res = mysqli_query($plink, 'SELECT id, label FROM test WHERE id = 1'))
+ printf("[013] Cannot run query on persistent connection of second DB user, [%d] %s\n",
+ mysqli_errno($plink), mysqli_error($plink));
+
+ if (!$row = mysqli_fetch_assoc($res))
+ printf("[014] Cannot run fetch result, [%d] %s\n",
+ mysqli_errno($plink), mysqli_error($plink));
+ mysqli_free_result($res);
+ var_dump($row);
+
+ if ($plink2 = my_mysqli_connect('p:' . $host, 'pcontest', 'newpass', $db, $port, $socket))
+ printf("[015] Can open more persistent connections than allowed, [%d] %s\n",
+ mysqli_connect_errno(), mysqli_connect_error());
+
+ ob_start();
+ phpinfo();
+ $phpinfo = strip_tags(ob_get_contents());
+ ob_end_clean();
+ $phpinfo = substr($phpinfo, stripos($phpinfo, 'MysqlI Support => enabled'), 500);
+ if (!preg_match('@Active Persistent Links\s+=>\s+(\d+)@ismU', $phpinfo, $matches))
+ printf("[016] Cannot get # of active persistent links from phpinfo()\n");
+
+ $num_plinks = $matches[1];
+ if ($num_plinks > (int)ini_get('mysqli.max_persistent'))
+ printf("[017] mysqli.max_persistent=%d allows %d open connections!\n", ini_get('mysqli.max_persistent'),$num_plinks);
+
+ mysqli_query($link, 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM pcontest');
+ mysqli_query($link, 'DROP USER pcontest');
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS test"))
+ printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+mysqli_query($link, 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM pcontest');
+mysqli_query($link, 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM pcontest@localhost');
+mysqli_query($link, 'DROP USER pcontest@localhost');
+mysqli_query($link, 'DROP USER pcontest');
+
+mysqli_close($link);
+?>
+--EXPECTF--
+array(2) {
+ [%u|b%"id"]=>
+ %unicode|string%(1) "1"
+ [%u|b%"label"]=>
+ %unicode|string%(1) "a"
+}
+array(2) {
+ [%u|b%"id"]=>
+ %unicode|string%(1) "1"
+ [%u|b%"label"]=>
+ %unicode|string%(1) "a"
+}
+
+Warning: %s: Too many open persistent links (%d) in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_pconn_reuse.phpt b/ext/mysqli/tests/mysqli_pconn_reuse.phpt
new file mode 100644
index 0000000..6e210bd
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_pconn_reuse.phpt
@@ -0,0 +1,91 @@
+--TEST--
+mysqli_pconnect() - reusing/caching persistent connections - TODO
+--SKIPIF--
+<?php
+die("skip TODO - we need to add a user level way to check if CHANGE_USER gets called by pconnect");
+
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--INI--
+mysqli.allow_persistent=1
+mysqli.max_persistent=2
+mysqli.max_links=2
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $host = 'p:' . $host;
+ if (!$link1 = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ printf("[001] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s, [%d] %s\n",
+ $host, $user, $db, $port, $socket, mysqli_connect_errno(), mysqli_connect_error());
+ }
+ if (!mysqli_query($link1, 'SET @pcondisabled = "Connection 1"'))
+ printf("[002] Cannot set user variable to check if we got the same persistent connection, [%d] %s\n",
+ mysqli_errno($link1), mysqli_error($link1));
+
+ if (!$link2 = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ printf("[003] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s, [%d] %s\n",
+ $host, $user, $db, $port, $socket, mysqli_connect_errno(), mysqli_connect_error());
+ }
+
+ if (!$res = mysqli_query($link1, 'SELECT @pcondisabled AS _test'))
+ printf("[004] [%d] %s\n", mysqli_errno($link2), mysqli_error($link2));
+
+ $row = mysqli_fetch_assoc($res);
+ printf("Connection 1 - SELECT @pcondisabled -> '%s'\n", $row['_test']);
+ mysqli_free_result($res);
+
+ if (!$res = mysqli_query($link2, 'SELECT @pcondisabled AS _test'))
+ printf("[005] [%d] %s\n", mysqli_errno($link2), mysqli_error($link2));
+
+ $row = mysqli_fetch_assoc($res);
+ printf("Connection 2 (no reuse) - SELECT @pcondisabled -> '%s'\n", $row['_test']);
+ $thread_id = mysqli_thread_id($link2);
+ printf("Connection 2 (no reuse) - Thread ID -> '%s'\n", $thread_id);
+ mysqli_free_result($res);
+
+ if (!mysqli_query($link2, 'SET @pcondisabled = "Connection 2"'))
+ printf("[006] Cannot set user variable to check if we got the same persistent connection, [%d] %s\n",
+ mysqli_errno($link2), mysqli_error($link2));
+
+ if (!$res = mysqli_query($link2, 'SELECT @pcondisabled AS _test'))
+ printf("[007] [%d] %s\n", mysqli_errno($link2), mysqli_error($link2));
+
+ $row = mysqli_fetch_assoc($res);
+ printf("Connection 2 - SELECT @pcondisabled -> '%s'\n", $row['_test']);
+ mysqli_free_result($res);
+
+ mysqli_close($link2);
+
+ /* reuse of existing persistent connection expected! */
+ if (!$link2 = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ printf("[008] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s, [%d] %s\n",
+ $host, $user, $db, $port, $socket, mysqli_connect_errno(), mysqli_connect_error());
+ }
+
+ if (!$res = mysqli_query($link2, 'SELECT @pcondisabled AS _test'))
+ printf("[009] [%d] %s\n", mysqli_errno($link2), mysqli_error($link2));
+
+ $row = mysqli_fetch_assoc($res);
+ printf("Connection 2 (reuse) - SELECT @pcondisabled -> '%s'\n", $row['_test']);
+ $thread_id_reuse = mysqli_thread_id($link2);
+ printf("Connection 2 (reuse) - Thread ID -> '%s'\n", $thread_id_reuse);
+ mysqli_free_result($res);
+
+ if ($thread_id != $thread_id_reuse)
+ printf("[010] Seems as if we have got a new connection, connections should have been cached and reused!\n");
+
+ mysqli_close($link1);
+ mysqli_close($link2);
+ print "done!";
+?>
+--EXPECTF--
+Connection 1 - SELECT @pcondisabled -> 'Connection 1'
+Connection 2 (no reuse) - SELECT @pcondisabled -> ''
+Connection 2 (no reuse) - Thread ID -> '%d'
+Connection 2 - SELECT @pcondisabled -> 'Connection 2'
+Connection 2 (reuse) - SELECT @pcondisabled -> 'Connection 2'
+Connection 2 (reuse) - Thread ID -> '%d'
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_pconn_twice.phpt b/ext/mysqli/tests/mysqli_pconn_twice.phpt
new file mode 100644
index 0000000..5630d4e
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_pconn_twice.phpt
@@ -0,0 +1,77 @@
+--TEST--
+Calling connect() on an open persistent connection to create a new persistent connection
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+?>
+--INI--
+mysqli.allow_persistent=1
+mysqli.max_persistent=-1
+mysqli.max_links=-1
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $host = 'p:' . $host;
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[001] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ if (true !== ($tmp = my_mysqli_real_connect($link, $host, $user, $passwd, $db, $port, $socket)))
+ printf("[003] Expecting boolean/true got %s/%s\n", gettype($tmp), $tmp);
+
+ /* it is undefined which pooled connection we get - thread ids may differ */
+
+ if (!($res = mysqli_query($link, "SELECT 'ok' AS it_works")) ||
+ !($row = mysqli_fetch_assoc($res)))
+ printf("[006] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ var_dump($row);
+ mysqli_free_result($res);
+
+ mysqli_close($link);
+
+ if (!$link = new my_mysqli($host, $user, $passwd, $db, $port, $socket))
+ printf("[007] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+
+ if (true !== ($tmp = $link->real_connect($host, $user, $passwd, $db, $port, $socket)))
+ printf("[009] Expecting boolean/true got %s/%s\n", gettype($tmp), $tmp);
+
+ /* it is undefined which pooled connection we get - thread ids may differ */
+
+ if (!($res = $link->query("SELECT 'works also with oo' AS syntax")) ||
+ !($row = $res->fetch_assoc()))
+ printf("[012] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ var_dump($row);
+ mysqli_free_result($res);
+
+ mysqli_close($link);
+
+ if (NULL !== ($tmp = $link->connect($host, $user, $passwd, $db, $port, $socket)))
+ printf("[013] Expecting NULL got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[014] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ if (NULL !== ($tmp = $link->connect($host, $user, $passwd, $db, $port, $socket)))
+ printf("[015] Expecting NULL got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--EXPECTF--
+array(1) {
+ [%u|b%"it_works"]=>
+ %unicode|string%(2) "ok"
+}
+array(1) {
+ [%u|b%"syntax"]=>
+ %unicode|string%(18) "works also with oo"
+}
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_pconnect.phpt b/ext/mysqli/tests/mysqli_pconnect.phpt
new file mode 100644
index 0000000..734029a
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_pconnect.phpt
@@ -0,0 +1,72 @@
+--TEST--
+mysqli_pconnect()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $host = 'p:' . $host;
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[002] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ mysqli_close($link);
+
+ $num = 20;
+ $connections = array();
+ for ($i = 0; $i < $num; $i++) {
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[003] Connect failed, [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+ $connections[] = $link;
+ }
+ while (count($connections)) {
+ do {
+ $index = mt_rand(0, $num);
+ } while (!isset($connections[$index]));
+ mysqli_close($connections[$index]);
+ unset($connections[$index]);
+ }
+
+
+ $connections = array();
+ $num = 20;
+ for ($i = 0; $i < $num; $i++) {
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[004] Connect failed, [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+ $connections[] = $link;
+ }
+ $left = $num;
+
+ while (count($connections) && $left > 0) {
+ do {
+ $index = mt_rand(0, $num);
+ } while (!isset($connections[$index]) && $left > 0);
+ if (mt_rand(0, 1) > 0) {
+ $left--;
+ mysqli_close($connections[$index]);
+ unset($connections[$index]);
+ } else {
+ $left--;
+ if (!$connections[$index] = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[004] Connect failed, [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+ }
+ flush();
+ }
+
+ while (count($connections)) {
+ do {
+ $index = mt_rand(0, $num);
+ } while (!isset($connections[$index]));
+ mysqli_close($connections[$index]);
+ unset($connections[$index]);
+ }
+
+ print "done!";
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_phpinfo.phpt b/ext/mysqli/tests/mysqli_phpinfo.phpt
new file mode 100644
index 0000000..e23a5f6
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_phpinfo.phpt
@@ -0,0 +1,72 @@
+--TEST--
+phpinfo() mysqli section
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ include("connect.inc");
+
+ @ob_clean();
+ ob_start();
+ phpinfo();
+ $phpinfo = ob_get_contents();
+ ob_end_clean();
+
+ /* all versions should at least dump this minimum information */
+ if (!stristr($phpinfo, "mysqli support"))
+ printf("[001] ext/mysqli should have exposed itself.\n");
+
+ if (!stristr($phpinfo, "client api library version"))
+ printf("[002] ext/mysqli should have exposed the library version.\n");
+
+ if (!stristr($phpinfo, "mysqli.default_host"))
+ printf("[003] php.ini setting mysqli.default_host not shown.\n");
+
+ if (!stristr($phpinfo, "mysqli.default_port"))
+ printf("[004] php.ini setting mysqli.default_port not shown.\n");
+
+ if (!stristr($phpinfo, "mysqli.default_pw"))
+ printf("[005] php.ini setting mysqli.default_pw not shown.\n");
+
+ if (!stristr($phpinfo, "mysqli.default_socket"))
+ printf("[006] php.ini setting mysqli.default_socket not shown.\n");
+
+ if (!stristr($phpinfo, "mysqli.default_user"))
+ printf("[007] php.ini setting mysqli.default_user not shown.\n");
+
+ if (!stristr($phpinfo, "mysqli.max_links"))
+ printf("[008] php.ini setting mysqli.max_links not shown.\n");
+
+ if (!stristr($phpinfo, "mysqli.reconnect"))
+ printf("[009] php.ini setting mysqli.reconnect not shown.\n");
+
+ if ($IS_MYSQLND) {
+ $expected = array(
+ 'mysqlnd statistics',
+ 'bytes_sent', 'bytes_received', 'packets_sent', 'packets_received',
+ 'protocol_overhead_in', 'protocol_overhead_out', 'result_set_queries',
+ 'non_result_set_queries', 'no_index_used', 'bad_index_used',
+ 'buffered_sets', 'unbuffered_sets', 'ps_buffered_sets', 'ps_unbuffered_sets',
+ 'flushed_normal_sets', 'flushed_ps_sets', 'rows_fetched_from_server',
+ 'rows_fetched_from_client', 'rows_skipped', 'copy_on_write_saved',
+ 'copy_on_write_performed', 'command_buffer_too_small', 'connect_success',
+ 'connect_failure', 'connection_reused', 'explicit_close', 'implicit_close',
+ 'disconnect_close', 'in_middle_of_command_close', 'explicit_free_result',
+ 'implicit_free_result', 'explicit_stmt_close', 'implicit_stmt_close',
+ 'size',
+ 'mysqli.allow_local_infile',
+ 'mysqli.allow_persistent', 'mysqli.max_persistent'
+ );
+ foreach ($expected as $k => $entry)
+ if (!stristr($phpinfo, $entry))
+ printf("[010] Could not find entry for '%s'\n", $entry);
+ }
+
+ print "done!";
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_ping.phpt b/ext/mysqli/tests/mysqli_ping.phpt
new file mode 100644
index 0000000..d9a134c
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_ping.phpt
@@ -0,0 +1,47 @@
+--TEST--
+mysqli_ping()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_ping()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (!is_null($tmp = @mysqli_ping($link, $link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ var_dump(mysqli_ping($link));
+
+ // provoke an error to check if mysqli_ping resets it
+ $res = mysqli_query($link, 'SELECT * FROM unknown_table');
+ if (!($errno = mysqli_errno($link)))
+ printf("[003] Statement should have caused an error\n");
+
+ var_dump(mysqli_ping($link));
+ if ($errno === mysqli_errno($link))
+ printf("[004] Error codes should have been reset\n");
+
+ mysqli_close($link);
+
+ if (!is_null($tmp = mysqli_ping($link)))
+ printf("[005] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--EXPECTF--
+bool(true)
+bool(true)
+
+Warning: mysqli_ping(): Couldn't fetch mysqli in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_poll.phpt b/ext/mysqli/tests/mysqli_poll.phpt
new file mode 100644
index 0000000..dd4f9b9
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_poll.phpt
@@ -0,0 +1,137 @@
+--TEST--
+int mysqli_poll() simple
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('connect.inc');
+require_once('skipifconnectfailure.inc');
+
+if (!$IS_MYSQLND)
+ die("skip mysqlnd only feature, compile PHP using --with-mysqli=mysqlnd");
+?>
+--FILE--
+<?php
+ require_once('connect.inc');
+
+ function get_connection() {
+ global $host, $user, $passwd, $db, $port, $socket;
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+ return $link;
+ }
+
+ if (!$link = get_connection())
+ printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+ if (NULL !== ($tmp = @mysqli_poll()))
+ printf("[002] Expecting NULL got %s\n", var_export($tmp, true));
+
+ $l = array($link);
+ if (NULL !== ($tmp = @mysqli_poll($l)))
+ printf("[003] Expecting NULL got %s\n", var_export($tmp, true));
+
+ $l = array($link); $n = NULL;
+ if (NULL !== ($tmp = @mysqli_poll($l, $n)))
+ printf("[004] Expecting NULL got %s\n", var_export($tmp, true));
+
+ $l = array($link); $n = NULL;
+ if (NULL !== ($tmp = @mysqli_poll($l, $n, $n)))
+ printf("[005] Expecting NULL got %s\n", var_export($tmp, true));
+
+ $l = array($link); $e = NULL; $r = NULL;
+ if (NULL !== ($tmp = @mysqli_poll($l, $e, $r, -1)))
+ printf("[007] Expecting boolean/false got %s/%s\n", gettype($tmp), var_export($tmp, true));
+
+ $l = array($link); $e = NULL; $r = NULL;
+ if (NULL !== ($tmp = @mysqli_poll($l, $e, $r, 0, -1)))
+ printf("[008] Expecting boolean/false got %s/%s\n", gettype($tmp), var_export($tmp, true));
+
+ $read = $error = $reject = array($link);
+ if (0 !== ($tmp = (mysqli_poll($read, $error, $reject, 0, 1))))
+ printf("[009] Expecting int/0 got %s/%s\n", gettype($tmp), var_export($tmp, true));
+
+
+ function poll_async($offset, $link, $links, $errors, $reject, $exp_ready, $use_oo_syntax) {
+
+ if ($exp_ready !== ($tmp = mysqli_poll($links, $errors, $reject, 0, 1000)))
+ printf("[%03d + 1] There should be %d links ready to read from, %d ready\n",
+ $exp_ready, $tmp);
+
+ foreach ($links as $mysqli) {
+ if ($use_oo_syntax) {
+ $res = $mysqli->reap_async_query();
+ } else {
+ $res = mysqli_reap_async_query($mysqli);
+ }
+ if (is_object($res)) {
+ printf("[%03d + 2] Can fetch resultset although no query has been run!\n", $offset);
+ } else if (mysqli_errno($mysqli) > 0) {
+ printf("[%03d + 3] Error indicated through links array: %d/%s",
+ $offset, mysqli_errno($mysqli), mysqli_error($mysqli));
+ } else {
+ printf("[%03d + 4] Cannot fetch and no error set - non resultset query (no SELECT)!\n", $offset);
+ }
+ }
+
+ foreach ($errors as $mysqli)
+ printf("[%03d + 5] Error on %d: %d/%s\n",
+ $offset, mysqli_thread_id($mysqli), mysqli_errno($mysqli), mysqli_error($mysqli));
+
+ foreach ($reject as $mysqli)
+ printf("[%03d + 6] Rejecting thread %d: %d/%s\n",
+ $offset, mysqli_thread_id($mysqli), mysqli_errno($mysqli), mysqli_error($mysqli));
+
+ }
+
+ // Connections on which no query has been send - 1
+ $link = get_connection();
+ $links = array($link);
+ $errors = array($link);
+ $reject = array($link);
+ poll_async(10, $link, $links, $errors, $reject, 0, false);
+ mysqli_close($link);
+
+ $link = get_connection();
+ $links = array($link);
+ $errors = array($link);
+ $reject = array($link);
+ poll_async(11, $link, $links, $errors, $reject, 0, true);
+ mysqli_close($link);
+
+ // Connections on which no query has been send - 2
+ // Difference: pass $links twice
+ $link = get_connection();
+ $links = array($link, $link);
+ $errors = array($link, $link);
+ $reject = array();
+ poll_async(12, $link, $links, $errors, $reject, 0, false);
+
+ // Connections on which no query has been send - 3
+ // Difference: pass two connections
+ $link = get_connection();
+ $links = array($link, get_connection());
+ $errors = array($link, $link);
+ $reject = array();
+ poll_async(13, $link, $links, $errors, $reject, 0, false);
+
+ // Reference mess...
+ $link = get_connection();
+ $links = array($link);
+ $errors = array($link);
+ $ref_errors =& $errors;
+ $reject = array();
+ poll_async(14, $link, $links, $ref_errors, $reject, 0, false);
+
+ print "done!";
+?>
+--EXPECTF--
+[010 + 6] Rejecting thread %d: 0/
+[011 + 6] Rejecting thread %d: 0/
+[012 + 6] Rejecting thread %d: 0/
+[012 + 6] Rejecting thread %d: 0/
+[013 + 6] Rejecting thread %d: 0/
+[013 + 6] Rejecting thread %d: 0/
+[014 + 6] Rejecting thread %d: 0/
+done!
diff --git a/ext/mysqli/tests/mysqli_poll_kill.phpt b/ext/mysqli/tests/mysqli_poll_kill.phpt
new file mode 100644
index 0000000..b068d64
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_poll_kill.phpt
@@ -0,0 +1,199 @@
+--TEST--
+int mysqli_poll() and kill
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('connect.inc');
+require_once('skipifconnectfailure.inc');
+
+if (!$IS_MYSQLND)
+ die("skip mysqlnd only feature, compile PHP using --with-mysqli=mysqlnd");
+?>
+--FILE--
+<?php
+ require_once('connect.inc');
+
+ function get_connection() {
+ global $host, $user, $passwd, $db, $port, $socket;
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+ return $link;
+ }
+
+ // Killing connection - 1
+
+ $link = get_connection();
+ if (true !== ($tmp = mysqli_query($link, "SELECT 1 AS 'processed before killed'", MYSQLI_ASYNC | MYSQLI_USE_RESULT)))
+ printf("[002] Expecting boolean/true got %s/%s\n", gettype($tmp), var_export($tmp, true));
+
+ // Sleep 0.1s - the asynchronous query should have been processed after the wait period
+ usleep(100000);
+ $thread_id = mysqli_thread_id($link);
+ mysqli_kill(get_connection(), $thread_id);
+
+ $links = array($link);
+ $errors = array($link);
+ $reject = array($link);
+
+ // Yes, 1 - the asynchronous query should have been processed
+ if (1 !== ($tmp = (mysqli_poll($links, $errors, $reject, 0, 10000))))
+ printf("[003] Expecting int/1 got %s/%s\n", gettype($tmp), var_export($tmp, true));
+
+ if (!is_array($links) || empty($links))
+ printf("[004] Expecting non-empty array got %s/%s\n", gettype($links), var_export($links, true));
+ else
+ foreach ($links as $link) {
+ if (is_object($res = mysqli_reap_async_query($link))) {
+ // Yes, you can fetch a result - the query has been processed
+ var_dump(mysqli_fetch_assoc($res));
+ mysqli_free_result($res);
+ } else if ($link->errno > 0) {
+ printf("[005] Error: %d\n", $link->errno);
+ }
+ }
+
+ // No error!
+ if (!is_array($errors) || !empty($errors))
+ printf("[006] Expecting non-empty array got %s/%s\n", gettype($errors), var_export($errors, true));
+
+ if (!is_array($reject) || !empty($reject))
+ printf("[007] Expecting empty array got %s/%s\n", gettype($reject), var_export($reject, true));
+
+ // Lets pass a dead connection
+ $links = array($link);
+ $errors = array($link);
+ $reject = array($link);
+ if (0 !== ($tmp = mysqli_poll($links, $errors, $reject, 1)))
+ printf("[008] There should be no connection ready! Returned %s/%s, expecting int/0.\n",
+ gettype($tmp), var_export($tmp, true));
+
+ if (!empty($errors))
+ printf("[009] There should be no errors but one rejected connection\n");
+
+ foreach ($reject as $mysqli)
+ if (mysqli_thread_id($mysqli) != $thread_id) {
+ printf("[010] Rejected thread %d should have rejected thread %d\n",
+ mysqli_thread_id($mysqli), $thread_id);
+ }
+
+ // Killing connection - 2
+
+ $link = get_connection();
+ if (true !== ($tmp = mysqli_query($link, "SELECT 1", MYSQLI_ASYNC | MYSQLI_USE_RESULT)))
+ printf("[011] Expecting boolean/true got %s/%s\n", gettype($tmp), var_export($tmp, true));
+
+ usleep(100000);
+ $thread_id = mysqli_thread_id($link);
+ mysqli_kill(get_connection(), $thread_id);
+
+ // Yes, 1 - fetch OK packet of kill!
+ $processed = 0;
+ do {
+ $links = array($link, $link);
+ $errors = array($link, $link);
+ $reject = array($link, $link);
+ $ready = mysqli_poll($links, $errors, $reject, 1);
+
+ if (!empty($errors)) {
+ foreach ($errors as $mysqli) {
+ printf("[012] Error on thread %d: %s/%s\n",
+ mysqli_thread_id($mysqli),
+ mysqli_errno($mysqli),
+ mysqli_error($mysqli));
+ }
+ break;
+ }
+
+ if (!empty($reject)) {
+ foreach ($reject as $mysqli) {
+ printf("[013] Rejecting thread %d: %s/%s\n",
+ mysqli_thread_id($mysqli),
+ mysqli_errno($mysqli),
+ mysqli_error($mysqli));
+ }
+ $processed += count($reject);
+ }
+
+ foreach ($links as $mysqli) {
+ if (is_object($res = mysqli_reap_async_query($mysqli))) {
+ printf("Fetching from thread %d...\n", mysqli_thread_id($mysqli));
+ var_dump(mysqli_fetch_assoc($res));
+ } else if (mysqli_errno($mysqli) > 0) {
+ printf("[014] %d/%s\n", mysqli_errno($mysqli), mysqli_error($mysqli));
+ }
+ $processed++;
+ }
+
+ } while ($processed < 2);
+
+
+ // Killing connection - 3
+
+ $link = get_connection();
+ $thread_id = mysqli_thread_id($link);
+ mysqli_kill(get_connection(), $thread_id);
+ // Sleep 0.1s to ensure the KILL gets recognized
+ usleep(100000);
+ if (false !== ($tmp = mysqli_query($link, "SELECT 1 AS 'processed before killed'", MYSQLI_ASYNC | MYSQLI_USE_RESULT)))
+ printf("[015] Expecting boolean/false got %s/%s\n", gettype($tmp), var_export($tmp, true));
+
+ $links = array($link);
+ $errors = array($link);
+ $reject = array($link);
+
+ if (0 !== ($tmp = (mysqli_poll($links, $errors, $reject, 0, 10000))))
+ printf("[016] Expecting int/0 got %s/%s\n", gettype($tmp), var_export($tmp, true));
+
+ if (!is_array($links) || empty($links))
+ printf("[017] Expecting non-empty array got %s/%s\n", gettype($links), var_export($links, true));
+ else
+ foreach ($links as $link) {
+ if (is_object($res = mysqli_reap_async_query($link))) {
+ // No, you cannot fetch the result
+ var_dump(mysqli_fetch_assoc($res));
+ mysqli_free_result($res);
+ } else if ($link->errno > 0) {
+ // But you are supposed to handle the error the way its shown here!
+ printf("[018] Error: %d/%s\n", $link->errno, $link->error);
+ }
+ }
+
+ // None of these will indicate an error, check errno on the list of returned connections!
+ if (!is_array($errors) || !empty($errors))
+ printf("[019] Expecting non-empty array got %s/%s\n", gettype($errors), var_export($errors, true));
+
+ if (!is_array($reject) || !empty($reject))
+ printf("[020] Expecting empty array got %s/%s\n", gettype($reject), var_export($reject, true));
+
+
+ mysqli_close($link);
+ print "done!";
+?>
+--XFAIL--
+To be fixed later. Minor issue about fetching error message from killed line
+--EXPECTF--
+array(1) {
+ [%u|b%"processed before killed"]=>
+ %unicode|string%(1) "1"
+}
+Fetching from thread %d...
+array(1) {
+ [1]=>
+ %unicode|string%(1) "1"
+}
+
+Warning: mysqli_reap_async_query(): Premature end of data (mysqlnd_wireprotocol.c:%d) in %s on line %d
+
+Warning: mysqli_reap_async_query(): RSET_HEADER %s
+
+Warning: mysqli_reap_async_query(): Error reading result set's header in %s on line %d
+
+Warning: Error while sending QUERY packet. %s
+
+Warning: mysqli_reap_async_query(): %s
+
+Warning: mysqli_reap_async_query(): Error reading result set's header in %s on line %d
+[018] Error: %d/%s
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_poll_mixing_insert_select.phpt b/ext/mysqli/tests/mysqli_poll_mixing_insert_select.phpt
new file mode 100644
index 0000000..9c02cf9
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_poll_mixing_insert_select.phpt
@@ -0,0 +1,184 @@
+--TEST--
+mysqli_poll() & INSERT SELECT
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('connect.inc');
+require_once('skipifconnectfailure.inc');
+
+if (!$IS_MYSQLND)
+ die("skip mysqlnd only feature, compile PHP using --with-mysqli=mysqlnd");
+?>
+--FILE--
+<?php
+ require_once('table.inc');
+
+ function get_connection() {
+ global $host, $user, $passwd, $db, $port, $socket;
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+ return $link;
+ }
+
+
+ // Note: some queries will fail! They are supposed to fail.
+ $queries = array(
+ 'CREATE TABLE IF NOT EXISTS bogus(id INT)',
+ 'SET @a = 1',
+ 'SELECT * FROM test ORDER BY id ASC LIMIT 2',
+ "INSERT INTO test(id, label) VALUES (100, 'z')",
+ 'SELECT * FROM test ORDER BY id ASC LIMIT 2',
+ 'SELECT',
+ 'UPDATE test SET id = 101 WHERE id > 3',
+ 'UPDATE_FIX test SET id = 101 WHERE id > 3',
+ 'DROP TABLE IF EXISTS bogus',
+ 'DELETE FROM test WHERE id = @a',
+ 'DELETE FROM test WHERE id = 1',
+ );
+
+ $link = get_connection();
+ $have_proc = false;
+ mysqli_real_query($link, "DROP PROCEDURE IF EXISTS p");
+ if (mysqli_real_query($link, 'CREATE PROCEDURE p(IN ver_in VARCHAR(25), OUT ver_out VARCHAR(25)) BEGIN SELECT ver_in INTO ver_out; END;')) {
+ $have_proc = true;
+ $queries[] = "CALL p('myversion', @version)";
+ }
+ mysqli_close($link);
+
+ $links = array();
+ for ($i = 0; $i < count($queries); $i++) {
+
+ $link = get_connection();
+
+ if (true !== ($tmp = mysqli_query($link, $queries[$i], MYSQLI_ASYNC | MYSQLI_USE_RESULT)))
+ printf("[002] Expecting true got %s/%s\n", gettype($tmp), var_export($tmp, true));
+
+ // WARNING KLUDGE NOTE
+ // Add a tiny delay to ensure that queries get executed in a certain order
+ // If your MySQL server is very slow the test may randomly fail!
+ usleep(20000);
+
+ $links[mysqli_thread_id($link)] = array(
+ 'query' => $queries[$i],
+ 'link' => $link,
+ 'processed' => false,
+ );
+ }
+
+ $saved_errors = array();
+ do {
+ $poll_links = $poll_errors = $poll_reject = array();
+ foreach ($links as $thread_id => $link) {
+ if (!$link['processed']) {
+ $poll_links[] = $link['link'];
+ $poll_errors[] = $link['link'];
+ $poll_reject[] = $link['link'];
+ }
+ }
+ if (0 == count($poll_links))
+ break;
+
+ if (0 == ($num_ready = mysqli_poll($poll_links, $poll_errors, $poll_reject, 0, 200000)))
+ continue;
+
+ if (!empty($poll_errors)) {
+ die(var_dump($poll_errors));
+ }
+
+ foreach ($poll_links as $link) {
+ $thread_id = mysqli_thread_id($link);
+ $links[$thread_id]['processed'] = true;
+
+ if (is_object($res = mysqli_reap_async_query($link))) {
+ // result set object
+ while ($row = mysqli_fetch_assoc($res)) {
+ // eat up all results
+ ;
+ }
+ mysqli_free_result($res);
+ } else {
+ // either there is no result (no SELECT) or there is an error
+ if (mysqli_errno($link) > 0) {
+ $saved_errors[$thread_id] = mysqli_errno($link);
+ printf("[003] '%s' caused %d\n", $links[$thread_id]['query'], mysqli_errno($link));
+ }
+ }
+ }
+
+ } while (true);
+
+ // Checking if all lines are still usable
+ foreach ($links as $thread_id => $link) {
+ if (isset($saved_errors[$thread_id]) &&
+ $saved_errors[$thread_id] != mysqli_errno($link['link'])) {
+ printf("[004] Error state not saved for query '%s', %d != %d\n", $link['query'],
+ $saved_errors[$thread_id], mysqli_errno($link['link']));
+ }
+
+ if (!$res = mysqli_query($link['link'], 'SELECT * FROM test WHERE id = 100'))
+ printf("[005] Expecting true got %s/%s\n", gettype($tmp), var_export($tmp, true));
+ if (!$row = mysqli_fetch_row($res))
+ printf("[006] Expecting true got %s/%s\n", gettype($tmp), var_export($tmp, true));
+
+ mysqli_free_result($res);
+ }
+
+ if ($res = mysqli_query($link['link'], "SELECT * FROM test WHERE id = 100")) {
+ $row = mysqli_fetch_assoc($res);
+ var_dump($row);
+ mysqli_free_result($res);
+ }
+
+ if ($have_proc && ($res = mysqli_query($link['link'], "SELECT @version as _version"))) {
+ $row = mysqli_fetch_assoc($res);
+ if ($row['_version'] != 'myversion') {
+ printf("[007] Check procedures\n");
+ }
+ mysqli_free_result($res);
+ }
+
+ foreach ($links as $link)
+ mysqli_close($link['link']);
+
+ $link = get_connection();
+ if (!mysqli_query($link, 'SELECT 1', MYSQLI_ASYNC))
+ printf("[008] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, 'SELECT 1', MYSQLI_ASYNC))
+ printf("[009] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ mysqli_close($link);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS test"))
+ printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS bogus"))
+ printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+mysqli_query($link, "DROP PROCEDURE IF EXISTS p");
+
+mysqli_close($link);
+?>
+
+--EXPECTF--
+[003] 'SELECT' caused 1064
+[003] 'UPDATE test SET id = 101 WHERE id > 3' caused 1062
+[003] 'UPDATE_FIX test SET id = 101 WHERE id > 3' caused 1064
+array(2) {
+ [%u|b%"id"]=>
+ %unicode|string%(3) "100"
+ [%u|b%"label"]=>
+ %unicode|string%(1) "z"
+}
+[009] [2014] %s
+done!
diff --git a/ext/mysqli/tests/mysqli_poll_reference.phpt b/ext/mysqli/tests/mysqli_poll_reference.phpt
new file mode 100644
index 0000000..ab2ed2a
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_poll_reference.phpt
@@ -0,0 +1,220 @@
+--TEST--
+mysqli_poll() & references
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('connect.inc');
+require_once('skipifconnectfailure.inc');
+
+if (!$IS_MYSQLND)
+ die("skip mysqlnd only feature, compile PHP using --with-mysqli=mysqlnd");
+
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ die("skip cannot connect");
+
+if (mysqli_get_server_version($link) < 50012)
+ die("skip Test needs SQL function SLEEP() available as of MySQL 5.0.12");
+
+?>
+--FILE--
+<?php
+ require_once('connect.inc');
+
+ function get_connection() {
+ global $host, $user, $passwd, $db, $port, $socket;
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+ return $link;
+ }
+
+
+ $mysqli1 = get_connection();
+ $mysqli2 = get_connection();
+
+ var_dump(mysqli_query($mysqli1, "SELECT SLEEP(0.10)", MYSQLI_ASYNC | MYSQLI_USE_RESULT));
+ var_dump(mysqli_query($mysqli2, "SELECT SLEEP(0.20)", MYSQLI_ASYNC | MYSQLI_USE_RESULT));
+
+ $processed = $loops = 0;
+ do {
+ $loops++;
+ if ($loops > 10) {
+ printf("[002] The queries should have finished already\n");
+ break;
+ }
+ // WARNING: All arrays point to the same object - this will give bogus results!
+ // The behaviour is in line with stream_select(). Be warned, be careful.
+ $links = $errors = $reject = array($mysqli1, $mysqli2);
+ if (0 == ($ready = mysqli_poll($links, $errors, $reject, 0, 50000))) {
+ continue;
+ }
+
+ foreach ($links as $link) {
+ if ($res = mysqli_reap_async_query($link)) {
+ mysqli_free_result($res);
+ }
+ $processed++;
+ }
+ } while ($processed < 2);
+
+ mysqli_close($mysqli1);
+ mysqli_close($mysqli2);
+
+ $mysqli1 = get_connection();
+ $mysqli2 = get_connection();
+
+ var_dump(mysqli_query($mysqli1, "SELECT SLEEP(0.10)", MYSQLI_ASYNC | MYSQLI_USE_RESULT));
+ var_dump(mysqli_query($mysqli2, "SELECT SLEEP(0.20)", MYSQLI_ASYNC | MYSQLI_USE_RESULT));
+
+ $processed = $loops = 0;
+ do {
+ $loops++;
+ if ($loops > 10) {
+ printf("[003] The queries should have finished already\n");
+ break;
+ }
+ // WARNING: All arrays point to the same object - this will give bogus results!
+ $links = $errors = array($mysqli1, $mysqli2);
+ $reject = array($mysqli1, $mysqli2);
+ if (0 == ($ready = mysqli_poll($links, $errors, $reject, 0, 50000))) {
+ continue;
+ }
+ foreach ($links as $link) {
+ if ($res = mysqli_reap_async_query($link)) {
+ mysqli_free_result($res);
+ }
+ $processed++;
+ }
+ } while ($processed < 2);
+
+ mysqli_close($mysqli1);
+ mysqli_close($mysqli2);
+
+ $mysqli1 = get_connection();
+ $mysqli2 = get_connection();
+
+ var_dump(mysqli_query($mysqli1, "SELECT SLEEP(0.10)", MYSQLI_ASYNC | MYSQLI_USE_RESULT));
+ var_dump(mysqli_query($mysqli2, "SELECT SLEEP(0.20)", MYSQLI_ASYNC | MYSQLI_USE_RESULT));
+
+ $processed = $loops = 0;
+ do {
+ $loops++;
+ if ($loops > 10) {
+ printf("[004] The queries should have finished already\n");
+ break;
+ }
+ // WARNING: All arrays point to the same object - this will give bogus results!
+ $links = array($mysqli1, $mysqli2);
+ $errors = $reject = array($mysqli1, $mysqli2);
+ if (0 == ($ready = mysqli_poll($links, $errors, $reject, 0, 50000))) {
+ continue;
+ }
+ foreach ($links as $link) {
+ if ($res = mysqli_reap_async_query($link)) {
+ mysqli_free_result($res);
+ }
+ $processed++;
+ }
+ } while ($processed < 2);
+
+ mysqli_close($mysqli1);
+ mysqli_close($mysqli2);
+
+ // This is bogus code and bogus usage - OK to throw no errors!
+ $mysqli1 = get_connection();
+ $mysqli2 = get_connection();
+
+ var_dump(mysqli_query($mysqli1, "SELECT SLEEP(0.10)", MYSQLI_ASYNC | MYSQLI_USE_RESULT));
+ $thread_id = mysqli_thread_id($mysqli2);
+ printf("Connection %d should be rejected...\n", $thread_id);
+
+ $processed = $loops = 0;
+ do {
+ $loops++;
+ if ($loops > 10) {
+ printf("[005] The queries should have finished already\n");
+ break;
+ }
+ $links = $errors = $reject = array($mysqli1, $mysqli2);
+ if (0 == ($ready = mysqli_poll($links, $errors, $reject, 0, 50000))) {
+ continue;
+ }
+ // WARNING: Due to the reference issue none of these should ever fire!
+ foreach ($reject as $link) {
+ printf("Connection %d was rejected...\n", mysqli_thread_id($link));
+ if (mysqli_thread_id($link) != $thread_id) {
+ printf("[006] Connector %d should have been rejected. But also %d has been rejected.",
+ $thread_id, mysqli_thread_id($link));
+ }
+ $processed++;
+ }
+ foreach ($errors as $link) {
+ printf("Connection %d has an error...\n", mysqli_thread_id($link));
+ $processed++;
+ }
+ foreach ($links as $link) {
+ if ($res = mysqli_reap_async_query($link)) {
+ mysqli_free_result($res);
+ $processed++;
+ }
+ }
+ } while ($processed < 2);
+
+ mysqli_close($mysqli1);
+ mysqli_close($mysqli2);
+
+ $mysqli1 = get_connection();
+ $mysqli2 = get_connection();
+
+ var_dump(mysqli_query($mysqli1, "SELECT SLEEP(0.10)", MYSQLI_ASYNC | MYSQLI_USE_RESULT));
+ var_dump(mysqli_query($mysqli2, "SELECT SLEEP(0.20)", MYSQLI_ASYNC | MYSQLI_USE_RESULT));
+
+ $processed = $loops = 0;
+ $all = array($mysqli1, $mysqli2);
+ do {
+ $loops++;
+ if ($loops > 10) {
+ printf("[006] The queries should have finished already\n");
+ break;
+ }
+ $links = $errors = $reject = $all;
+ ob_start();
+ if (0 == ($ready = mysqli_poll($links, $errors, $reject, 0, 50000))) {
+ $tmp = ob_get_contents();
+ ob_end_clean();
+ if ($tmp != '') {
+ printf("Expected error:\n%s\n", $tmp);
+ break;
+ }
+ continue;
+ }
+ foreach ($links as $link) {
+ if ($res = mysqli_reap_async_query($link)) {
+ mysqli_free_result($res);
+ }
+ $processed++;
+ }
+ } while ($processed < 2);
+
+ $ready = mysqli_poll($links, $errors, $reject, 0, 50000);
+ mysqli_close($mysqli1);
+ mysqli_close($mysqli2);
+
+ print "done!";
+?>
+--EXPECTF--
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+Connection %d should be rejected...
+Connection %d was rejected...
+bool(true)
+bool(true)
+
+Warning: mysqli_poll(): All arrays passed are clear in %s on line %d
+done!
diff --git a/ext/mysqli/tests/mysqli_prepare.phpt b/ext/mysqli/tests/mysqli_prepare.phpt
new file mode 100644
index 0000000..d6d6c09
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_prepare.phpt
@@ -0,0 +1,135 @@
+--TEST--
+mysqli_prepare()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_prepare()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_prepare($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (false !== ($tmp = @mysqli_prepare($link, false)))
+ printf("[003] Expecting boolean/false, got %s\n", gettype($tmp));
+
+ if (!$res = mysqli_query($link, "SELECT id, label FROM test", MYSQLI_USE_RESULT))
+ printf("[004] [%d] %s, next test will fail\n", mysqli_errno($link), mysqli_error($link));
+
+ if (false !== ($tmp = mysqli_prepare($link, 'SELECT id FROM test WHERE id > ?')))
+ printf("[005] Expecting boolean/false, got %s, [%d] %s\n", gettype($tmp), mysqli_errno($link), mysqli_error($link));
+
+ mysqli_free_result($res);
+
+ if (!is_object(($stmt = mysqli_prepare($link, 'SELECT id FROM test'))) || !mysqli_stmt_execute($stmt))
+ printf("[006][%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ mysqli_stmt_close($stmt);
+
+
+ if (!mysqli_query($link, "DROP TABLE IF EXISTS test2"))
+ printf("[007] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!is_object(($stmt = mysqli_prepare($link, 'CREATE TABLE test2(id INT) ENGINE =' . $engine))) || !mysqli_stmt_execute($stmt))
+ printf("[008] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ mysqli_stmt_close($stmt);
+
+
+ if (!is_object(($stmt = mysqli_prepare($link, 'INSERT INTO test2(id) VALUES(?)'))))
+ printf("[009] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $id = 1;
+ if (!mysqli_stmt_bind_param($stmt, 'i', $id) || !mysqli_stmt_execute($stmt))
+ printf("[010] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ mysqli_stmt_close($stmt);
+
+ if (!is_object(($stmt = mysqli_prepare($link, 'REPLACE INTO test2(id) VALUES (?)'))))
+ printf("[011] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $id = 2;
+ if (!mysqli_stmt_bind_param($stmt, 'i', $id) || !mysqli_stmt_execute($stmt))
+ printf("[012] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ mysqli_stmt_close($stmt);
+
+ if (!is_object(($stmt = mysqli_prepare($link, 'UPDATE test2 SET id = ? WHERE id = ?'))))
+ printf("[013] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $id = 3;
+ $where = 2;
+ if (!mysqli_stmt_bind_param($stmt, 'ii', $id, $where) || !mysqli_stmt_execute($stmt))
+ printf("[014] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ mysqli_stmt_close($stmt);
+
+ if (!is_object(($stmt = mysqli_prepare($link, 'DELETE FROM test2 WHERE id = ?'))))
+ printf("[015] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $where = 3;
+ if (!mysqli_stmt_bind_param($stmt, 'i', $where) || !mysqli_stmt_execute($stmt))
+ printf("[016] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ mysqli_stmt_close($stmt);
+
+ if (!is_object(($stmt = mysqli_prepare($link, 'SET @testvar = ?'))))
+ printf("[017] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $testvar = 'testvar';
+ if (!mysqli_stmt_bind_param($stmt, 's', $testvar) || !mysqli_stmt_execute($stmt))
+ printf("[018] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ mysqli_stmt_close($stmt);
+
+ if (!is_object(($stmt = mysqli_prepare($link, "DO GET_LOCK('testlock', 1)"))))
+ printf("[019] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ mysqli_stmt_close($stmt);
+
+ if (!is_object(($stmt = mysqli_prepare($link, 'SELECT id, @testvar FROM test2'))))
+ printf("[020] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $id = $testvar = null;
+ if (!mysqli_stmt_execute($stmt) || !mysqli_stmt_bind_result($stmt, $id, $testvar))
+ printf("[021] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ while (mysqli_stmt_fetch($stmt)) {
+ if (('testvar' !== $testvar) || (1 !== $id))
+ printf("[022] Expecting 'testvar'/1, got %s/%s. [%d] %s\n",
+ $testvar, $id, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ }
+
+ var_dump(mysqli_stmt_prepare($stmt, 'SELECT 1; SELECT 2'));
+
+ mysqli_stmt_close($stmt);
+
+ if (!is_null($tmp = @mysqli_stmt_prepare($link, 'SELECT id FROM test', 'foo')))
+ printf("[023] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_close($link);
+
+ if (!is_null($tmp = @mysqli_stmt_prepare($link, 'SELECT id FROM test')))
+ printf("[024] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS test"))
+ printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS test2"))
+ printf("[c003] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+mysqli_close($link);
+?>
+--EXPECTF--
+bool(false)
+done!
diff --git a/ext/mysqli/tests/mysqli_prepare_no_object.phpt b/ext/mysqli/tests/mysqli_prepare_no_object.phpt
new file mode 100644
index 0000000..e45de69
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_prepare_no_object.phpt
@@ -0,0 +1,46 @@
+--TEST--
+mysqli_prepare() - no object on failure
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require('table.inc');
+
+ if (false !== ($tmp = mysqli_prepare($link, false)))
+ printf("[001] Expecting boolean/false, got %s/%s\n", gettype($tmp), (is_object($tmp) ? var_dump($tmp, true) : $tmp));
+ printf("a) [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (false !== ($tmp = mysqli_prepare($link, '')))
+ printf("[002] Expecting boolean/false, got %s/%s\n", gettype($tmp), (is_object($tmp) ? var_dump($tmp, true) : $tmp));
+ printf("b) [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ mysqli_close($link);
+
+ if (!$mysqli = new my_mysqli($host, $user, $passwd, $db, $port, $socket))
+ printf("[003] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ if (false !== ($tmp = $mysqli->prepare(false)))
+ printf("[004] Expecting boolean/false, got %s/%s\n", gettype($tmp), (is_object($tmp) ? var_dump($tmp, true) : $tmp));
+ printf("c) [%d] %s\n", $mysqli->errno, $mysqli->error);
+
+ if (false !== ($tmp = $mysqli->prepare('')))
+ printf("[005] Expecting boolean/false, got %s/%s\n", gettype($tmp), (is_object($tmp) ? var_dump($tmp, true) : $tmp));
+ printf("c) [%d] %s\n", $mysqli->errno, $mysqli->error);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+require_once("clean_table.inc");
+?>
+--EXPECTF--
+a) [1065] Query was empty
+b) [1065] Query was empty
+c) [1065] Query was empty
+c) [1065] Query was empty
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_ps_select_union.phpt b/ext/mysqli/tests/mysqli_ps_select_union.phpt
new file mode 100644
index 0000000..fed81b3
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_ps_select_union.phpt
@@ -0,0 +1,275 @@
+--TEST--
+Prepared Statements and SELECT UNION
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+ require_once("table.inc");
+
+ // Regular (non-prepared) queries
+ print "Using CAST('somestring' AS CHAR)...\n";
+ if (!($res = $link->query("SELECT CAST('one' AS CHAR) AS column1 UNION SELECT CAST('three' AS CHAR) UNION SELECT CAST('two' AS CHAR)")))
+ printf("[001] [%d] %s\n", $link->errno, $link->error);
+
+ $data = array();
+ while ($row = $res->fetch_assoc()) {
+ $data[] = $row['column1'];
+ var_dump($row['column1']);
+ }
+ $res->free();
+
+ // Prepared Statements
+ if (!($stmt = $link->prepare("SELECT CAST('one' AS CHAR) AS column1 UNION SELECT CAST('three' AS CHAR) UNION SELECT CAST('two' AS CHAR)")))
+ printf("[002] [%d] %s\n", $link->errno, $link->error);
+
+ $column1 = null;
+ if (!$stmt->execute() || !$stmt->bind_result($column1))
+ printf("[003] [%d] %s\n", $stmt->errno, $stmt->error);
+
+ $index = 0;
+ while ($stmt->fetch()) {
+ if ($data[$index] != $column1) {
+ printf("[004] Row %d, expecting %s/%s got %s/%s\n",
+ $index + 1, gettype($data[$index]), $data[$index], gettype($column1), $column1);
+ }
+ $index++;
+ }
+ $stmt->close();
+
+ if ($IS_MYSQLND) {
+ /*
+ Advantage mysqlnd -
+ The metadata mysqlnd has availabe after prepare is better than
+ the one made availabe by the MySQL Client Library (libmysql).
+ "libmysql" will give wrong results and that is OK -
+ http://bugs.mysql.com/bug.php?id=47483
+ */
+ if (!($stmt = $link->prepare("SELECT CAST('one' AS CHAR) AS column1 UNION SELECT CAST('three' AS CHAR) UNION SELECT CAST('two' AS CHAR)")))
+ printf("[005] [%d] %s\n", $link->errno, $link->error);
+
+ $column1 = null;
+ /* Note: bind_result before execute */
+ if (!$stmt->bind_result($column1) || !$stmt->execute())
+ printf("[006] [%d] %s\n", $stmt->errno, $stmt->error);
+
+ $index = 0;
+ while ($stmt->fetch()) {
+ if ($data[$index] != $column1) {
+ printf("[007] Row %d, expecting %s/%s got %s/%s\n",
+ $index + 1, gettype($data[$index]), $data[$index], gettype($column1), $column1);
+ }
+ $index++;
+ }
+ $stmt->close();
+ }
+
+ // Regular (non-prepared) queries
+ print "Mixing CAST('somestring'AS CHAR), integer and CAST(integer AS CHAR)...\n";
+ if (!($res = $link->query("SELECT 1 AS column1 UNION SELECT CAST('three' AS CHAR) UNION SELECT CAST(2 AS CHAR)")))
+ printf("[008] [%d] %s\n", $link->errno, $link->error);
+
+ $data = array();
+ while ($row = $res->fetch_assoc()) {
+ $data[] = $row['column1'];
+ }
+ $res->free();
+
+ // Prepared Statements
+ if (!($stmt = $link->prepare("SELECT 1 AS column1 UNION SELECT CAST('three' AS CHAR) UNION SELECT CAST(2 AS CHAR)")))
+ printf("[009] [%d] %s\n", $link->errno, $link->error);
+
+ $column1 = null;
+ if (!$stmt->execute() || !$stmt->bind_result($column1))
+ printf("[010] [%d] %s\n", $stmt->errno, $stmt->error);
+
+ $index = 0;
+ while ($stmt->fetch()) {
+ if ($data[$index] != $column1) {
+ printf("[011] Row %d, expecting %s/%s got %s/%s\n",
+ $index + 1, gettype($data[$index]), $data[$index], gettype($column1), $column1);
+ }
+ var_dump($column1);
+ $index++;
+ }
+ $stmt->close();
+
+ if ($IS_MYSQLND) {
+ /* Advantage mysqlnd - see above... */
+ if (!($stmt = $link->prepare("SELECT 1 AS column1 UNION SELECT CAST('three' AS CHAR) UNION SELECT CAST(2 AS CHAR)")))
+ printf("[012] [%d] %s\n", $link->errno, $link->error);
+
+ $column1 = null;
+ if (!$stmt->bind_result($column1) || !$stmt->execute())
+ printf("[013] [%d] %s\n", $stmt->errno, $stmt->error);
+
+ $index = 0;
+ while ($stmt->fetch()) {
+ if ($data[$index] != $column1) {
+ printf("[014] Row %d, expecting %s/%s got %s/%s\n",
+ $index + 1, gettype($data[$index]), $data[$index], gettype($column1), $column1);
+ }
+ $index++;
+ }
+ $stmt->close();
+ }
+
+ print "Using integer only...\n";
+ if (!($res = $link->query("SELECT 1 AS column1 UNION SELECT 303 UNION SELECT 2")))
+ printf("[015] [%d] %s\n", $link->errno, $link->error);
+
+ $data = array();
+ while ($row = $res->fetch_assoc()) {
+ $data[] = $row['column1'];
+ }
+ $res->free();
+
+ // Prepared Statements
+ if (!($stmt = $link->prepare("SELECT 1 AS column1 UNION SELECT 303 UNION SELECT 2")))
+ printf("[016] [%d] %s\n", $link->errno, $link->error);
+
+ $column1 = null;
+ if (!$stmt->execute() || !$stmt->bind_result($column1))
+ printf("[017] [%d] %s\n", $stmt->errno, $stmt->error);
+
+ $index = 0;
+ while ($stmt->fetch()) {
+ if ($data[$index] != $column1) {
+ printf("[018] Row %d, expecting %s/%s got %s/%s\n",
+ $index + 1, gettype($data[$index]), $data[$index], gettype($column1), $column1);
+ }
+ var_dump($column1);
+ $index++;
+ }
+ $stmt->close();
+
+ if ($IS_MYSQLND) {
+ /* Advantage mysqlnd - see above */
+ if (!($stmt = $link->prepare("SELECT 1 AS column1 UNION SELECT 303 UNION SELECT 2")))
+ printf("[019] [%d] %s\n", $link->errno, $link->error);
+
+ $column1 = null;
+ if (!$stmt->bind_result($column1) || !$stmt->execute())
+ printf("[020] [%d] %s\n", $stmt->errno, $stmt->error);
+
+ $index = 0;
+ while ($stmt->fetch()) {
+ if ($data[$index] != $column1) {
+ printf("[021] Row %d, expecting %s/%s got %s/%s\n",
+ $index + 1, gettype($data[$index]), $data[$index], gettype($column1), $column1);
+ }
+ $index++;
+ }
+ $stmt->close();
+ }
+
+ print "Testing bind_param(), strings only...\n";
+ $two = 'two';
+ $three = 'three';
+ if (!($stmt = $link->prepare("SELECT 'one' AS column1 UNION SELECT ? UNION SELECT ?")))
+ printf("[022] [%d] %s\n", $stmt->errno, $stmt->error);
+
+ $column1 = null;
+ if (!$stmt->bind_param('ss', $three, $two) || !$stmt->execute() || !$stmt->bind_result($column1))
+ printf("[023] [%d] %s\n", $stmt->errno, $stmt->error);
+
+ $index = 0;
+ $data = array();
+ while ($stmt->fetch()) {
+ $data[$index++] = $column1;
+ var_dump($column1);
+ }
+ $stmt->close();
+
+ if ($IS_MYSQLND) {
+ /* Advantage mysqlnd - see above */
+ $two = 'two';
+ $three = 'three';
+ if (!($stmt = $link->prepare("SELECT 'one' AS column1 UNION SELECT ? UNION SELECT ?")))
+ printf("[024] [%d] %s\n", $stmt->errno, $stmt->error);
+
+ $column1 = null;
+ if (!$stmt->bind_param('ss', $three, $two) || !$stmt->bind_result($column1) || !$stmt->execute())
+ printf("[025] [%d] %s\n", $stmt->errno, $stmt->error);
+
+ $index = 0;
+ while ($stmt->fetch()) {
+ if ($data[$index] != $column1) {
+ printf("[26] Row %d, expecting %s/%s, got %s/%s\n",
+ $index + 1, gettype($data[$index]), $data[$index], gettype($column1), $column1);
+ }
+ $index++;
+ }
+ $stmt->close();
+ }
+
+ print "Testing bind_param(), strings only, with CAST AS CHAR...\n";
+ $two = 'two';
+ $three = 'three beers are more than enough';
+ if (!($stmt = $link->prepare("SELECT CAST('one' AS CHAR) AS column1 UNION SELECT CAST(? AS CHAR) UNION SELECT CAST(? AS CHAR)")))
+ printf("[027] [%d] %s\n", $stmt->errno, $stmt->error);
+
+ $column1 = null;
+ if (!$stmt->bind_param('ss', $three, $two) || !$stmt->execute() || !$stmt->bind_result($column1))
+ printf("[028] [%d] %s\n", $stmt->errno, $stmt->error);
+
+ $index = 0;
+ $data = array();
+ while ($stmt->fetch()) {
+ $data[$index++] = $column1;
+ var_dump($column1);
+ }
+ $stmt->close();
+
+ if ($IS_MYSQLND) {
+ /* Advantage mysqlnd - see above */
+ $two = 'two';
+ $three = 'three beers are more than enough';
+ if (!($stmt = $link->prepare("SELECT CAST('one' AS CHAR) AS column1 UNION SELECT CAST(? AS CHAR) UNION SELECT CAST(? AS CHAR)")))
+ printf("[029] [%d] %s\n", $stmt->errno, $stmt->error);
+
+ $column1 = null;
+ if (!$stmt->bind_param('ss', $three, $two) || !$stmt->bind_result($column1) || !$stmt->execute())
+ printf("[030] [%d] %s\n", $stmt->errno, $stmt->error);
+
+ $index = 0;
+ while ($stmt->fetch()) {
+ if ($data[$index] != $column1) {
+ printf("[31] Row %d, expecting %s/%s, got %s/%s\n",
+ $index + 1, gettype($data[$index]), $data[$index], gettype($column1), $column1);
+ }
+ $index++;
+ }
+ $stmt->close();
+ }
+
+ $link->close();
+
+ print "done!";
+?>
+--EXPECTF--
+Using CAST('somestring' AS CHAR)...
+%unicode|string%(3) "one"
+%unicode|string%(5) "three"
+%unicode|string%(3) "two"
+Mixing CAST('somestring'AS CHAR), integer and CAST(integer AS CHAR)...
+%unicode|string%(1) "1"
+%unicode|string%(5) "three"
+%unicode|string%(1) "2"
+Using integer only...
+int(1)
+int(303)
+int(2)
+Testing bind_param(), strings only...
+%unicode|string%(3) "one"
+%unicode|string%(5) "three"
+%unicode|string%(3) "two"
+Testing bind_param(), strings only, with CAST AS CHAR...
+%unicode|string%(3) "one"
+%unicode|string%(32) "three beers are more than enough"
+%unicode|string%(3) "two"
+done!
diff --git a/ext/mysqli/tests/mysqli_query.phpt b/ext/mysqli/tests/mysqli_query.phpt
new file mode 100644
index 0000000..73bebe1
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_query.phpt
@@ -0,0 +1,141 @@
+--TEST--
+mysqli_query()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_query()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_query($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (false !== ($tmp = @mysqli_query($link, '')))
+ printf("[002a] Expecting boolean/false got %s/%s\n", gettype($tmp), $tmp);
+
+ if (NULL !== ($tmp = @mysqli_query($link, "SELECT 1 AS a", MYSQLI_USE_RESULT, "foo")))
+ printf("[003] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (false !== ($tmp = mysqli_query($link, 'THIS IS NOT SQL')))
+ printf("[004] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (false !== ($tmp = mysqli_query($link, "SELECT 'this is sql but with backslash g'\g")))
+ printf("[005] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if ((0 === mysqli_errno($link)) || ('' == mysqli_error($link)))
+ printf("[006] mysqli_errno()/mysqli_error should return some error\n");
+
+ if (!$res = mysqli_query($link, "SELECT 'this is sql but with semicolon' AS valid ; "))
+ printf("[007] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ var_dump(mysqli_fetch_assoc($res));
+ mysqli_free_result($res);
+
+ if (!$res = mysqli_query($link, "SELECT 'a' AS ''"))
+ printf("[007a] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ var_dump($tmp = mysqli_fetch_assoc($res));
+ var_dump($tmp[""]);
+ mysqli_free_result($res);
+
+ if (false !== ($res = mysqli_query($link, 'SELECT "this is sql but with semicolon" AS valid ; SHOW VARIABLES')))
+ printf("[008] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (mysqli_get_server_version($link) > 50000) {
+ // let's try to play with stored procedures
+ mysqli_query($link, 'DROP PROCEDURE IF EXISTS p');
+ if (mysqli_query($link, 'CREATE PROCEDURE p(OUT ver_param VARCHAR(25)) BEGIN SELECT VERSION() INTO ver_param; END;')) {
+ $res = mysqli_query($link, 'CALL p(@version)');
+ $res = mysqli_query($link, 'SELECT @version AS p_version');
+
+ $tmp = mysqli_fetch_assoc($res);
+ if (!is_array($tmp) || empty($tmp) || !isset($tmp['p_version']) || ('' == $tmp['p_version'])) {
+ printf("[008a] Expecting array [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ var_dump($tmp);
+ }
+
+ mysqli_free_result($res);
+ } else {
+ printf("[009] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ mysqli_query($link, 'DROP FUNCTION IF EXISTS f');
+ if (mysqli_query($link, 'CREATE FUNCTION f( ver_param VARCHAR(25)) RETURNS VARCHAR(25) DETERMINISTIC RETURN ver_param;')) {
+ $res = mysqli_query($link, 'SELECT f(VERSION()) AS f_version');
+
+ $tmp = mysqli_fetch_assoc($res);
+ if (!is_array($tmp) || empty($tmp) || !isset($tmp['f_version']) || ('' == $tmp['f_version'])) {
+ printf("[009a] Expecting array [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ var_dump($tmp);
+ }
+
+ mysqli_free_result($res);
+ } else {
+ printf("[010] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+ }
+
+ if (!is_object($res = mysqli_query($link, "SELECT id FROM test ORDER BY id", MYSQLI_USE_RESULT)))
+ printf("[011] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ mysqli_free_result($res);
+
+ if (!is_object($res = mysqli_query($link, "SELECT id FROM test ORDER BY id", MYSQLI_STORE_RESULT)))
+ printf("[012] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ mysqli_free_result($res);
+
+ $valid = array(MYSQLI_USE_RESULT, MYSQLI_STORE_RESULT);
+ do {
+ $mode = mt_rand(-1000, 1000);
+ } while (in_array($mode, $valid));
+
+ if (false !== ($res = @mysqli_query($link, "SELECT id FROM test ORDER BY id", $mode)))
+ printf("[013] Invalid mode should return false got %s/%s, [%d] %s\n",
+ gettype($res), (is_object($res)) ? 'object' : $res,
+ mysqli_errno($link), mysqli_error($link));
+
+
+ mysqli_close($link);
+
+ if (NULL !== ($tmp = mysqli_query($link, "SELECT id FROM test")))
+ printf("[011] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS test"))
+ printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+@mysqli_query($link, "DROP FUNCTION IF EXISTS f");
+@mysqli_query($link, 'DROP PROCEDURE IF EXISTS p');
+
+mysqli_close($link);
+?>
+--EXPECTF--
+array(1) {
+ [%u|b%"valid"]=>
+ %unicode|string%(30) "this is sql but with semicolon"
+}
+array(1) {
+ [%u|b%""]=>
+ %unicode|string%(1) "a"
+}
+%unicode|string%(1) "a"
+
+Warning: mysqli_query(): Couldn't fetch mysqli in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_query_iterators.phpt b/ext/mysqli/tests/mysqli_query_iterators.phpt
new file mode 100644
index 0000000..2577aa7
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_query_iterators.phpt
@@ -0,0 +1,201 @@
+--TEST--
+mysqli iterators
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ require('table.inc');
+
+ echo "--- Testing default ---\n";
+ if (!is_object($res = mysqli_query($link, "SELECT id FROM test ORDER BY id")))
+ printf("[011] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ else {
+ foreach ($res as $row) {
+ var_dump($row);
+ }
+ echo "======\n";
+ foreach ($res as $row) {
+ var_dump($row);
+ }
+ mysqli_free_result($res);
+ foreach ($res as $row) {
+ var_dump($row);
+ }
+ }
+ echo "--- Testing USE_RESULT ---\n";
+ if (!is_object($res = mysqli_query($link, "SELECT id FROM test ORDER BY id", MYSQLI_USE_RESULT)))
+ printf("[011] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ else {
+ foreach ($res as $row) {
+ var_dump($row);
+ }
+ echo "======\n";
+ foreach ($res as $row) {
+ var_dump($row);
+ }
+ mysqli_free_result($res);
+ }
+
+ echo "--- Testing STORE_RESULT ---\n";
+ if (!is_object($res = mysqli_query($link, "SELECT id FROM test ORDER BY id", MYSQLI_STORE_RESULT)))
+ printf("[012] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ else {
+ foreach ($res as $row) {
+ var_dump($row);
+ }
+ echo "======\n";
+ foreach ($res as $row) {
+ var_dump($row);
+ }
+ mysqli_free_result($res);
+ }
+
+ mysqli_close($link);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+--- Testing default ---
+array(1) {
+ ["id"]=>
+ string(1) "1"
+}
+array(1) {
+ ["id"]=>
+ string(1) "2"
+}
+array(1) {
+ ["id"]=>
+ string(1) "3"
+}
+array(1) {
+ ["id"]=>
+ string(1) "4"
+}
+array(1) {
+ ["id"]=>
+ string(1) "5"
+}
+array(1) {
+ ["id"]=>
+ string(1) "6"
+}
+======
+array(1) {
+ ["id"]=>
+ string(1) "1"
+}
+array(1) {
+ ["id"]=>
+ string(1) "2"
+}
+array(1) {
+ ["id"]=>
+ string(1) "3"
+}
+array(1) {
+ ["id"]=>
+ string(1) "4"
+}
+array(1) {
+ ["id"]=>
+ string(1) "5"
+}
+array(1) {
+ ["id"]=>
+ string(1) "6"
+}
+
+Warning: main(): Couldn't fetch mysqli_result in %s on line %d
+--- Testing USE_RESULT ---
+array(1) {
+ ["id"]=>
+ string(1) "1"
+}
+array(1) {
+ ["id"]=>
+ string(1) "2"
+}
+array(1) {
+ ["id"]=>
+ string(1) "3"
+}
+array(1) {
+ ["id"]=>
+ string(1) "4"
+}
+array(1) {
+ ["id"]=>
+ string(1) "5"
+}
+array(1) {
+ ["id"]=>
+ string(1) "6"
+}
+======
+
+Warning: main(): Data fetched with MYSQLI_USE_RESULT can be iterated only once in %s on line %d
+--- Testing STORE_RESULT ---
+array(1) {
+ ["id"]=>
+ string(1) "1"
+}
+array(1) {
+ ["id"]=>
+ string(1) "2"
+}
+array(1) {
+ ["id"]=>
+ string(1) "3"
+}
+array(1) {
+ ["id"]=>
+ string(1) "4"
+}
+array(1) {
+ ["id"]=>
+ string(1) "5"
+}
+array(1) {
+ ["id"]=>
+ string(1) "6"
+}
+======
+array(1) {
+ ["id"]=>
+ string(1) "1"
+}
+array(1) {
+ ["id"]=>
+ string(1) "2"
+}
+array(1) {
+ ["id"]=>
+ string(1) "3"
+}
+array(1) {
+ ["id"]=>
+ string(1) "4"
+}
+array(1) {
+ ["id"]=>
+ string(1) "5"
+}
+array(1) {
+ ["id"]=>
+ string(1) "6"
+}
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_query_local_infile_large.phpt b/ext/mysqli/tests/mysqli_query_local_infile_large.phpt
new file mode 100644
index 0000000..76bc415
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_query_local_infile_large.phpt
@@ -0,0 +1,103 @@
+--TEST--
+mysql_query(LOAD DATA LOCAL INFILE) with large data set (10MB)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+
+$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+if (!$link)
+ die(sprintf("skip Can't connect [%d] %s", mysqli_connect_errno(), mysqli_connect_error()));
+
+include_once("local_infile_tools.inc");
+if ($msg = check_local_infile_support($link, $engine))
+ die(sprintf("skip %s, [%d] %s", $msg, $link->errno, $link->error));
+
+mysqli_close($link);
+?>
+--INI--
+mysqli.allow_local_infile=1
+--FILE--
+<?php
+ // Create a large CVS file
+ $file = tempnam(sys_get_temp_dir(), 'mysqli_test.cvs');
+ if (!$fp = fopen($file, 'w'))
+ printf("[001] Cannot create CVS file '%s'\n", $file);
+
+ $data = str_repeat("a", 127) . ";" . str_repeat("b", 127) . "\n";
+
+ $runtime = 5;
+ $max_bytes = 1024 * 1024 * 10;
+
+ $start = microtime(true);
+ $bytes = 0;
+ $rowno = 0;
+ while (($bytes < $max_bytes) && ((microtime(true) - $start) < $runtime)) {
+ if ((version_compare(PHP_VERSION, '5.9.9', '>') == 1))
+ $bytes += fwrite($fp, (binary)(++$rowno . ";" . $data));
+ else
+ $bytes += fwrite($fp, ++$rowno . ";" . $data);
+ }
+ fclose($fp);
+ printf("Filesize in bytes: %d\nRows: %d\n", $bytes, $rowno);
+
+ require_once("connect.inc");
+ if (!($link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)))
+ printf("[002] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+ if (!mysqli_query($link, "DROP TABLE IF EXISTS test") ||
+ !mysqli_query($link, "CREATE TABLE test(id INT, col1 VARCHAR(255), col2 VARCHAR(255)) ENGINE = " . $engine))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, sprintf("LOAD DATA LOCAL INFILE '%s' INTO TABLE test FIELDS TERMINATED BY ';'", mysqli_real_escape_string($link, $file))))
+ printf("[004] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if ((!is_string(mysqli_info($link))) || ('' == mysqli_info($link))) {
+ printf("[005] [%d] %s, mysqli_info not set \n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ if (!($res = mysqli_query($link, "SELECT COUNT(*) AS _num FROM test")))
+ printf("[006] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $row = mysqli_fetch_assoc($res);
+ if (($row["_num"] != $rowno))
+ printf("[007] Expecting %d rows, found %d\n", $rowno, $row["_num"]);
+
+ mysqli_free_result($res);
+
+ $random = mt_rand(1, $rowno);
+ if (!$res = mysqli_query($link, "SELECT id, col1, col2 FROM test WHERE id = " . $random))
+ printf("[008] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $row = mysqli_fetch_assoc($res);
+ var_dump($row);
+ mysqli_free_result($res);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+$file = tempnam(sys_get_temp_dir(), 'mysqli_test.cvs');
+if (file_exists($file))
+ unlink($file);
+
+require_once("connect.inc");
+if (!($link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS test"))
+ printf("[c002] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+?>
+--EXPECTF--
+Filesize in bytes: %d
+Rows: %d
+array(3) {
+ [%u|b%"id"]=>
+ %unicode|string%(%d) "%d"
+ [%u|b%"col1"]=>
+ %unicode|string%(127) "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ [%u|b%"col2"]=>
+ %unicode|string%(127) "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
+}
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_query_stored_proc.phpt b/ext/mysqli/tests/mysqli_query_stored_proc.phpt
new file mode 100644
index 0000000..10bf86b
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_query_stored_proc.phpt
@@ -0,0 +1,195 @@
+--TEST--
+mysqli_query() - Stored Procedures
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+require_once('connect.inc');
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ die(sprintf('skip Cannot connect to MySQL, [%d] %s.', mysqli_connect_errno(), mysqli_connect_error()));
+}
+if (mysqli_get_server_version($link) <= 50000) {
+ die(sprintf('skip Needs MySQL 5.0+, found version %d.', mysqli_get_server_version($link)));
+}
+?>
+--FILE--
+<?php
+ require_once('connect.inc');
+ require_once('table.inc');
+
+ if (!mysqli_query($link, 'DROP PROCEDURE IF EXISTS p'))
+ printf("[001] [%d] %s.\n", mysqli_errno($link), mysqli_error($link));
+
+ if (mysqli_query($link, 'CREATE PROCEDURE p() READS SQL DATA BEGIN SELECT id, label FROM test ORDER BY id ASC;
+END;')) {
+ /* stored proc which returns one result set */
+ if (mysqli_multi_query($link, 'CALL p()')) {
+ do {
+ if ($res = mysqli_use_result($link)) {
+ // skip results, don't fetch all from server
+ var_dump(mysqli_fetch_assoc($res));
+ mysqli_free_result($res);
+ }
+ } while (mysqli_more_results($link) && mysqli_next_result($link));
+
+ } else {
+ printf("[003] Cannot call SP, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ if (mysqli_multi_query($link, 'CALL p()')) {
+ do {
+ if ($res = mysqli_store_result($link)) {
+ // fetch all results from server, but skip on client side
+ var_dump(mysqli_fetch_assoc($res));
+ mysqli_free_result($res);
+ }
+ } while (mysqli_more_results($link) && mysqli_next_result($link));
+
+ } else {
+ printf("[004] Cannot call SP, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ if (mysqli_multi_query($link, 'CALL p()')) {
+ do {
+ if ($res = mysqli_store_result($link)) {
+ // fetch all results from server, but skip on client side
+ var_dump(mysqli_fetch_assoc($res));
+ while (mysqli_fetch_assoc($res))
+ ;
+ mysqli_free_result($res);
+ }
+ } while (mysqli_more_results($link) && mysqli_next_result($link));
+
+ } else {
+ printf("[005] Cannot call SP, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ } else {
+ printf("[002] Cannot create SP, [%d] %s.\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ if (!mysqli_query($link, 'DROP PROCEDURE IF EXISTS p'))
+ printf("[006] [%d] %s.\n", mysqli_errno($link), mysqli_error($link));
+
+ if (mysqli_query($link, 'CREATE PROCEDURE p() READS SQL DATA BEGIN SELECT id, label FROM test ORDER BY id ASC; SELECT id FROM test ORDER BY id ASC; END;')) {
+ /* stored proc which returns two result sets */
+
+ if (mysqli_multi_query($link, 'CALL p()')) {
+ do {
+ if ($res = mysqli_store_result($link)) {
+ // fetch all results from server, but skip on client side
+ var_dump(mysqli_fetch_assoc($res));
+ mysqli_free_result($res);
+ }
+ } while (mysqli_more_results($link) && mysqli_next_result($link));
+
+ } else {
+ printf("[008] Cannot call SP, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ } else {
+ printf("[007] Cannot create SP, [%d] %s.\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ if (!mysqli_query($link, 'DROP PROCEDURE IF EXISTS p'))
+ printf("[009] [%d] %s.\n", mysqli_errno($link), mysqli_error($link));
+
+ if (mysqli_real_query($link, 'CREATE PROCEDURE p(OUT ver_param VARCHAR(25)) BEGIN SELECT VERSION() INTO ver_param; END;')) {
+ /* no result set, just output parameter */
+ if (!mysqli_query($link, 'CALL p(@version)'))
+ printf("[011] Cannot call SP, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, "SET @version = 'unknown'"))
+ printf("[012] Cannot reset user variable, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, 'CALL p(@version)'))
+ printf("[013] Cannot call SP, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$res = mysqli_query($link, 'SELECT @version as _vers'))
+ printf("[014] Cannot fetch user variable, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$row = mysqli_fetch_assoc($res) ||
+ $row['_vers'] == 'unknown')
+ printf("[015] Results seem wrong, got %s, [%d] %s\n",
+ $row['_vers'],
+ mysqli_errno($link), mysqli_error($link));
+ mysqli_free_result($res);
+
+ } else {
+ printf("[010] Cannot create SP, [%d] %s.\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ if (!mysqli_query($link, 'DROP PROCEDURE IF EXISTS p'))
+ printf("[016] [%d] %s.\n", mysqli_errno($link), mysqli_error($link));
+
+ if (mysqli_real_query($link, 'CREATE PROCEDURE p(IN ver_in VARCHAR(25), OUT ver_out VARCHAR(25)) BEGIN SELECT ver_in INTO ver_out; END;')) {
+ /* no result set, one input, one output parameter */
+ if (!mysqli_query($link, "CALL p('myversion', @version)"))
+ printf("[018] Cannot call SP, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, "SET @version = 'unknown'"))
+ printf("[019] Cannot reset user variable, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, "CALL p('myversion', @version)"))
+ printf("[020] Cannot call SP, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$res = mysqli_query($link, 'SELECT @version as _vers'))
+ printf("[021] Cannot fetch user variable, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$row = mysqli_fetch_assoc($res) ||
+ $row['_vers'] == 'myversion')
+ printf("[022] Results seem wrong, got %s, [%d] %s\n",
+ $row['_vers'],
+ mysqli_errno($link), mysqli_error($link));
+ mysqli_free_result($res);
+
+ } else {
+ printf("[017] Cannot create SP, [%d] %s.\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS test"))
+ printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+@mysqli_query($link, "DROP PROCEDURE IS EXISTS p");
+
+mysqli_close($link);
+?>
+--EXPECTF--
+array(2) {
+ [%u|b%"id"]=>
+ %unicode|string%(1) "1"
+ [%u|b%"label"]=>
+ %unicode|string%(1) "a"
+}
+array(2) {
+ [%u|b%"id"]=>
+ %unicode|string%(1) "1"
+ [%u|b%"label"]=>
+ %unicode|string%(1) "a"
+}
+array(2) {
+ [%u|b%"id"]=>
+ %unicode|string%(1) "1"
+ [%u|b%"label"]=>
+ %unicode|string%(1) "a"
+}
+array(2) {
+ [%u|b%"id"]=>
+ %unicode|string%(1) "1"
+ [%u|b%"label"]=>
+ %unicode|string%(1) "a"
+}
+array(1) {
+ [%u|b%"id"]=>
+ %unicode|string%(1) "1"
+}
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_query_unicode.phpt b/ext/mysqli/tests/mysqli_query_unicode.phpt
new file mode 100644
index 0000000..478ccbd
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_query_unicode.phpt
@@ -0,0 +1,133 @@
+--TEST--
+mysqli_query() - unicode (cyrillic)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+require_once('connect.inc');
+require_once('table.inc');
+if (!$res = mysqli_query($link, "SHOW CHARACTER SET LIKE 'utf8'"))
+ die("skip UTF8 chatset seems not available");
+mysqli_free_result($res);
+mysqli_close($link);
+?>
+--FILE--
+<?php
+ include_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_query()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_query($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require_once('table.inc');
+
+ if (TRUE !== ($tmp = @mysqli_query($link, "set names utf8")))
+ printf("[002.5] Expecting TRUE, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (NULL !== ($tmp = @mysqli_query($link, "SELECT 1 AS колона", MYSQLI_USE_RESULT, "foo")))
+ printf("[003] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (false !== ($tmp = mysqli_query($link, 'това не е еÑкюел')))
+ printf("[004] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (false !== ($tmp = mysqli_query($link, "SELECT 'това е еÑкюел, но ÑÑŠÑ Ð¾Ð±Ñ€Ð°Ñ‚Ð½Ð° наклонена и g'\g")))
+ printf("[005] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if ((0 === mysqli_errno($link)) || ('' == mysqli_error($link)))
+ printf("[006] mysqli_errno()/mysqli_error should return some error\n");
+
+ if (!$res = mysqli_query($link, "SELECT 'това еÑкюел, но Ñ Ñ‚Ð¾Ñ‡ÐºÐ° и запетаÑ' AS правилен ; "))
+ printf("[007] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ var_dump(mysqli_fetch_assoc($res));
+ mysqli_free_result($res);
+
+ if (false !== ($res = mysqli_query($link, "SELECT 'това еÑкюел, но Ñ Ñ‚Ð¾Ñ‡ÐºÐ° и запетаÑ' AS правилен ; SHOW VARIABLES")))
+ printf("[008] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (mysqli_get_server_version($link) > 50000) {
+ // let's try to play with stored procedures
+ mysqli_query($link, 'DROP PROCEDURE IF EXISTS процедурка');
+ if (mysqli_query($link, 'CREATE PROCEDURE процедурка(OUT верÑÐ¸Ñ VARCHAR(25)) BEGIN SELECT VERSION() INTO верÑиÑ; END;')) {
+ $res = mysqli_query($link, 'CALL процедурка(@version)');
+ $res = mysqli_query($link, 'SELECT @version AS п_верÑиÑ');
+
+ $tmp = mysqli_fetch_assoc($res);
+ if (!is_array($tmp) || empty($tmp) || !isset($tmp['п_верÑиÑ']) || ('' == $tmp['п_верÑиÑ'])) {
+ printf("[008a] Expecting array [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ var_dump($tmp);
+ }
+
+ mysqli_free_result($res);
+ } else {
+ printf("[009] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ mysqli_query($link, 'DROP FUNCTION IF EXISTS функцийка');
+ if (mysqli_query($link, 'CREATE FUNCTION функцийка( параметър_верÑÐ¸Ñ VARCHAR(25)) RETURNS VARCHAR(25) DETERMINISTIC RETURN параметър_верÑиÑ;')) {
+ $res = mysqli_query($link, 'SELECT функцийка(VERSION()) AS Ñ„_верÑиÑ');
+
+ $tmp = mysqli_fetch_assoc($res);
+ if (!is_array($tmp) || empty($tmp) || !isset($tmp['Ñ„_верÑиÑ']) || ('' == $tmp['Ñ„_верÑиÑ'])) {
+ printf("[009a] Expecting array [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ var_dump($tmp);
+ }
+
+ mysqli_free_result($res);
+ } else {
+ printf("[010] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+ }
+
+ /*
+ Trying to test what Ramil suggests in http://bugs.mysql.com/bug.php?id=29576
+ However, this won't work, because we're lacking MYSQLI_SET_CHARSET_NAME.
+ if ((version_compare(PHP_VERSION, '5.9.9', '>') == 1)) {
+ if (mysqli_get_server_version() > 50002) {
+ @mysqli_query($link, "DROP USER IF EXISTS 'теÑÑ‚'@'%'");
+ if (TRUE !== mysqli_query($link, "CREATE USER 'теÑÑ‚'@'%'")) {
+ var_dump(mysqli_error($link);
+ }
+ }
+ if (TRUE !== mysqli_query($link, "GRANT SELECT ON $db.* TO 'теÑÑ‚'@'%' IDENTIFIED BY 'парола'")) {
+ var_dump(mysqli_error($link);
+ } else {
+ $link2 = mysqli_init();
+ if (!(mysqli_real_connect($link2, $host, "теÑÑ‚", 'парола', $db, $port, $socket))) {
+ printf("[011] Cannot connect to the server using host=%s, user=%s, passwd=парола, dbname=%s, port=%s, socket=%s, [%d] %s\n",
+ $host, "теÑÑ‚", $db, $port, $socket,
+ mysqli_connect_errno(), mysqli_connect_error());
+ }
+ mysqli_close($link2);
+ if (mysqli_get_server_version() > 50002) {
+ if (!mysqli_query($link, "DROP USER 'теÑÑ‚'@'%'"))
+ printf("[013] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ } else {
+ printf("[015] Cannot create user or grant privileges, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+ }
+ }
+ }
+ */
+
+ mysqli_close($link);
+
+ if (NULL !== ($tmp = mysqli_query($link, "SELECT id FROM test")))
+ printf("[014] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--EXPECTF--
+array(1) {
+ [%u|b%"правилен"]=>
+ %unicode|string%(%d) "това еÑкюел, но Ñ Ñ‚Ð¾Ñ‡ÐºÐ° и запетаÑ"
+}
+
+Warning: mysqli_query(): Couldn't fetch mysqli in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_real_connect.phpt b/ext/mysqli/tests/mysqli_real_connect.phpt
new file mode 100644
index 0000000..5477ea1
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_real_connect.phpt
@@ -0,0 +1,221 @@
+--TEST--
+mysqli_real_connect()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ include("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (NULL !== ($tmp = @mysqli_real_connect($link)))
+ printf("[001a] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (NULL !== ($tmp = @mysqli_real_connect($link, $link)))
+ printf("[001b] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (NULL !== ($tmp = @mysqli_real_connect($link, $link, $link)))
+ printf("[001c] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (NULL !== ($tmp = @mysqli_real_connect($link, $link, $link, $link)))
+ printf("[001d] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (NULL !== ($tmp = @mysqli_real_connect($link, $link, $link, $link, $link)))
+ printf("[001e] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (NULL !== ($tmp = @mysqli_real_connect($link, $link, $link, $link, $link, $link)))
+ printf("[001f] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (NULL !== ($tmp = @mysqli_real_connect($link, $link, $link, $link, $link, $link, $link)))
+ printf("[001g] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ // ( mysqli link [, string hostname [, string username [, string passwd [, string dbname [, int port [, string socket [, int flags]]]]]]]
+ if (NULL !== ($tmp = @mysqli_real_connect($link, $link, $link, $link, $link, $link, $link, $link)))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$link = mysqli_init())
+ printf("[002] mysqli_init() failed\n");
+
+ if (!mysqli_real_connect($link, $host, $user, $passwd, $db, $port, $socket))
+ printf("[003] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ mysqli_close($link);
+ if (!$link = mysqli_init())
+ printf("[004] mysqli_init() failed\n");
+
+ if (false !== ($tmp = mysqli_real_connect($link, $host, $user . 'unknown_really', $passwd . 'non_empty', $db, $port, $socket)))
+ printf("[005] Expecting boolean/false got %s/%s. Can connect to the server using host=%s, user=%s, passwd=***non_empty, dbname=%s, port=%s, socket=%s\n", gettype($tmp), $tmp, $host, $user . 'unknown_really', $db, $port, $socket);
+
+ // Run the following tests without an anoynmous MySQL user and use a password for the test user!
+ ini_set('mysqli.default_socket', $socket);
+ if (!mysqli_real_connect($link, $host, $user, $passwd, $db, $port)) {
+ printf("[006] Usage of mysqli.default_socket failed\n");
+ } else {
+ mysqli_close($link);
+ if (!$link = mysqli_init())
+ printf("[007] mysqli_init() failed\n");
+ }
+
+ ini_set('mysqli.default_port', $port);
+ if (!mysqli_real_connect($link, $host, $user, $passwd, $db)) {
+ printf("[008] Usage of mysqli.default_port failed\n");
+ } else {
+ mysqli_close($link);
+ if (!$link = mysqli_init())
+ printf("[009] mysqli_init() failed\n");
+ }
+
+ ini_set('mysqli.default_pw', $passwd);
+ if (!mysqli_real_connect($link, $host, $user)) {
+ printf("[010] Usage of mysqli.default_pw failed\n") ;
+ } else {
+ mysqli_close($link);
+ if (!$link = mysqli_init())
+ printf("[011] mysqli_init() failed\n");
+ }
+
+ ini_set('mysqli.default_user', $user);
+ if (!mysqli_real_connect($link, $host)) {
+ printf("[012] Usage of mysqli.default_user failed\n") ;
+ } else {
+ mysqli_close($link);
+ if (!$link = mysqli_init())
+ printf("[011] mysqli_init() failed\n");
+ }
+
+ ini_set('mysqli.default_host', $host);
+ if (!mysqli_real_connect($link)) {
+ printf("[014] Usage of mysqli.default_host failed\n") ;
+ } else {
+ mysqli_close($link);
+ if (!$link = mysqli_init())
+ printf("[015] mysqli_init() failed\n");
+ }
+
+ // CLIENT_MULTI_STATEMENTS - should be disabled silently
+ if (!mysqli_real_connect($link, $host, $user, $passwd, $db, $port, $socket, 65536))
+ printf("[016] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if ($res = mysqli_query($link, "SELECT 1 AS a; SELECT 2 AS b")) {
+ printf("[017] Should have failed. CLIENT_MULTI_STATEMENT should have been disabled.\n");
+ var_dump($res->num_rows);
+ mysqli_next_result($link);
+ $res = mysqli_store_result($link);
+ var_dump($res->num_rows);
+ }
+
+
+ mysqli_close($link);
+ if (!$link = mysqli_init())
+ printf("[018] mysqli_init() failed\n");
+
+ if (ini_get('open_basedir')) {
+ // CLIENT_LOCAL_FILES should be blocked - but how to test it ?!
+
+ if (!mysqli_real_connect($link, $host, $user, $passwd, $db, $port, $socket, 128))
+ printf("[019] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $filename = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'mysqli_real_connect_phpt';
+ if (!$fp = fopen($filename, 'w'))
+ printf("[020] Cannot open temporary file %s\n", $filename);
+
+ fwrite($fp, '100;z');
+ fclose($fp);
+
+ // how do we test if gets forbidden because of a missing right or the flag, this test is partly bogus ?
+ if (mysqli_query($link, "LOAD DATA LOCAL INFILE '$filename' INTO TABLE test FIELDS TERMINATED BY ';'"))
+ printf("[021] LOAD DATA INFILE should have been forbidden!\n");
+
+ unlink($filename);
+ }
+
+ mysqli_close($link);
+ @var_dump($link);
+
+ if ($IS_MYSQLND) {
+ ini_set('mysqli.default_host', 'p:' . $host);
+ $link = mysqli_init();
+ if (!@mysqli_real_connect($link)) {
+ printf("[022] Usage of mysqli.default_host=p:%s (persistent) failed\n", $host) ;
+ } else {
+ if (!$res = mysqli_query($link, "SELECT 'mysqli.default_host (persistent)' AS 'testing'"))
+ printf("[023] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ $tmp = mysqli_fetch_assoc($res);
+ if ($tmp['testing'] !== 'mysqli.default_host (persistent)') {
+ printf("[024] Result looks strange - check manually, [%d] %s\n",
+ mysqli_errno($link), mysqli_error($link));
+ var_dump($tmp);
+ }
+ mysqli_free_result($res);
+ mysqli_close($link);
+ }
+
+ ini_set('mysqli.default_host', 'p:');
+ $link = mysqli_init();
+ if (@mysqli_real_connect($link)) {
+ printf("[025] Usage of mysqli.default_host=p: did not fail\n") ;
+ mysqli_close($link);
+ }
+ @mysqli_close($link);
+ }
+
+ if (NULL !== ($tmp = mysqli_real_connect($link, $host, $user, $passwd, $db, $port, $socket)))
+ printf("[026] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Warning: mysqli_real_connect(): (%s/%d): Access denied for user '%s'@'%s' (using password: YES) in %s on line %d
+object(mysqli)#%d (%d) {
+ [%u|b%"affected_rows"]=>
+ NULL
+ [%u|b%"client_info"]=>
+ %s
+ [%u|b%"client_version"]=>
+ int(%d)
+ [%u|b%"connect_errno"]=>
+ int(%d)
+ [%u|b%"connect_error"]=>
+ NULL
+ [%u|b%"errno"]=>
+ %s
+ [%u|b%"error"]=>
+ %s
+ [%u|b%"error_list"]=>
+ NULL
+ [%u|b%"field_count"]=>
+ NULL
+ [%u|b%"host_info"]=>
+ NULL
+ [%u|b%"info"]=>
+ NULL
+ [%u|b%"insert_id"]=>
+ NULL
+ [%u|b%"server_info"]=>
+ NULL
+ [%u|b%"server_version"]=>
+ NULL
+ [%u|b%"stat"]=>
+ NULL
+ [%u|b%"sqlstate"]=>
+ NULL
+ [%u|b%"protocol_version"]=>
+ NULL
+ [%u|b%"thread_id"]=>
+ NULL
+ [%u|b%"warning_count"]=>
+ NULL
+}
+
+Warning: mysqli_real_connect(): Couldn't fetch mysqli in %s on line %d
+done!
diff --git a/ext/mysqli/tests/mysqli_real_connect_pconn.phpt b/ext/mysqli/tests/mysqli_real_connect_pconn.phpt
new file mode 100644
index 0000000..4cc1819
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_real_connect_pconn.phpt
@@ -0,0 +1,155 @@
+--TEST--
+mysqli_real_connect() - persistent connections
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+require_once('connect.inc');
+if (!$IS_MYSQLND)
+ die("skip mysqlnd only test");
+?>
+--INI--
+mysqli.allow_persistent=1
+mysqli.max_persistent=10
+--FILE--
+<?php
+ require_once("connect.inc");
+ $host = 'p:' . $host;
+
+ if (!$link = mysqli_init())
+ printf("[002] mysqli_init() failed\n");
+
+ if (!mysqli_real_connect($link, $host, $user, $passwd, $db, $port, $socket))
+ printf("[003] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ mysqli_close($link);
+ if (!$link = mysqli_init())
+ printf("[004] mysqli_init() failed\n");
+
+ if (false !== ($tmp = mysqli_real_connect($link, $host, $user . 'unknown_really', $passwd . 'non_empty', $db, $port, $socket)))
+ printf("[005] Expecting boolean/false got %s/%s. Can connect to the server using host=%s, user=%s, passwd=***non_empty, dbname=%s, port=%s, socket=%s\n", gettype($tmp), $tmp, $host, $user . 'unknown_really', $db, $port, $socket);
+
+ // Run the following tests without an anoynmous MySQL user and use a password for the test user!
+ ini_set('mysqli.default_socket', $socket);
+ if (!mysqli_real_connect($link, $host, $user, $passwd, $db, $port)) {
+ printf("[006] Usage of mysqli.default_socket failed\n");
+ } else {
+ mysqli_close($link);
+ if (!$link = mysqli_init())
+ printf("[007] mysqli_init() failed\n");
+ }
+
+ ini_set('mysqli.default_port', $port);
+ if (!mysqli_real_connect($link, $host, $user, $passwd, $db)) {
+ printf("[008] Usage of mysqli.default_port failed\n");
+ } else {
+ mysqli_close($link);
+ if (!$link = mysqli_init())
+ printf("[009] mysqli_init() failed\n");
+ }
+
+ ini_set('mysqli.default_pw', $passwd);
+ if (!mysqli_real_connect($link, $host, $user)) {
+ printf("[010] Usage of mysqli.default_pw failed\n") ;
+ } else {
+ mysqli_close($link);
+ if (!$link = mysqli_init())
+ printf("[011] mysqli_init() failed\n");
+ }
+
+ ini_set('mysqli.default_user', $user);
+ if (!mysqli_real_connect($link, $host)) {
+ printf("[012] Usage of mysqli.default_user failed\n") ;
+ } else {
+ mysqli_close($link);
+ if (!$link = mysqli_init())
+ printf("[011] mysqli_init() failed\n");
+ }
+
+ ini_set('mysqli.default_host', $host);
+ if (!mysqli_real_connect($link)) {
+ printf("[014] Usage of mysqli.default_host failed\n") ;
+ } else {
+ mysqli_close($link);
+ if (!$link = mysqli_init())
+ printf("[015] mysqli_init() failed\n");
+ }
+
+ // CLIENT_MULTI_STATEMENTS - should be disabled silently
+ if (!mysqli_real_connect($link, $host, $user, $passwd, $db, $port, $socket, 65536))
+ printf("[016] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if ($res = mysqli_query($link, "SELECT 1 AS a; SELECT 2 AS b")) {
+ printf("[017] Should have failed. CLIENT_MULTI_STATEMENT should have been disabled.\n");
+ var_dump($res->num_rows);
+ mysqli_next_result($link);
+ $res = mysqli_store_result($link);
+ var_dump($res->num_rows);
+ }
+
+
+ mysqli_close($link);
+ if (!$link = mysqli_init())
+ printf("[018] mysqli_init() failed\n");
+
+ if (ini_get('open_basedir')) {
+ // CLIENT_LOCAL_FILES should be blocked - but how to test it ?!
+
+ if (!mysqli_real_connect($link, $host, $user, $passwd, $db, $port, $socket, 128))
+ printf("[019] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $filename = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'mysqli_real_connect_phpt';
+ if (!$fp = fopen($filename, 'w'))
+ printf("[020] Cannot open temporary file %s\n", $filename);
+
+ fwrite($fp, '100;z');
+ fclose($fp);
+
+ // how do we test if gets forbidden because of a missing right or the flag, this test is partly bogus ?
+ if (mysqli_query($link, "LOAD DATA LOCAL INFILE '$filename' INTO TABLE test FIELDS TERMINATED BY ';'"))
+ printf("[021] LOAD DATA INFILE should have been forbidden!\n");
+
+ unlink($filename);
+ }
+
+ mysqli_close($link);
+
+ if ($IS_MYSQLND) {
+ $link = mysqli_init();
+ if (!@mysqli_real_connect($link)) {
+ printf("[022] Usage of mysqli.default_host=p:%s (persistent) failed\n", $host) ;
+ } else {
+ if (!$res = mysqli_query($link, "SELECT 'mysqli.default_host (persistent)' AS 'testing'"))
+ printf("[023] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ $tmp = mysqli_fetch_assoc($res);
+ if ($tmp['testing'] !== 'mysqli.default_host (persistent)') {
+ printf("[024] Result looks strange - check manually, [%d] %s\n",
+ mysqli_errno($link), mysqli_error($link));
+ var_dump($tmp);
+ }
+ mysqli_free_result($res);
+ mysqli_close($link);
+ }
+
+ ini_set('mysqli.default_host', 'p:');
+ $link = mysqli_init();
+ if (@mysqli_real_connect($link)) {
+ printf("[025] Usage of mysqli.default_host=p: did not fail\n") ;
+ mysqli_close($link);
+ }
+ }
+
+ if (NULL === ($tmp = mysqli_real_connect($link, $host, $user, $passwd, $db, $port, $socket)))
+ printf("[026] Expecting not NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Warning: mysqli_real_connect(): (%s/%d): Access denied for user '%s'@'%s' (using password: YES) in %s on line %d
+done!
diff --git a/ext/mysqli/tests/mysqli_real_escape_string.phpt b/ext/mysqli/tests/mysqli_real_escape_string.phpt
new file mode 100644
index 0000000..6c37258
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_real_escape_string.phpt
@@ -0,0 +1,58 @@
+--TEST--
+mysqli_real_escape_string()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (NULL !== ($tmp = @mysqli_real_escape_string()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (NULL !== ($tmp = @mysqli_real_escape_string($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (NULL !== ($tmp =@mysqli_real_escape_string($link, "foo", "foo")))
+ printf("[003] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if ('\\\\' !== ($tmp = mysqli_real_escape_string($link, '\\')))
+ printf("[004] Expecting \\\\, got %s\n", $tmp);
+
+ if ('\"' !== ($tmp = mysqli_real_escape_string($link, '"')))
+ printf("[005] Expecting \", got %s\n", $tmp);
+
+ if ("\'" !== ($tmp = mysqli_real_escape_string($link, "'")))
+ printf("[006] Expecting ', got %s\n", $tmp);
+
+ if ("\\n" !== ($tmp = mysqli_real_escape_string($link, "\n")))
+ printf("[007] Expecting \\n, got %s\n", $tmp);
+
+ if ("\\r" !== ($tmp = mysqli_real_escape_string($link, "\r")))
+ printf("[008] Expecting \\r, got %s\n", $tmp);
+
+ if ("foo\\0bar" !== ($tmp = mysqli_real_escape_string($link, "foo" . chr(0) . "bar")))
+ printf("[009] Expecting %s, got %s\n", "foo\\0bar", $tmp);
+
+ mysqli_close($link);
+
+ if (NULL !== ($tmp = mysqli_real_escape_string($link, 'foo')))
+ printf("[010] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ /* Make sure that the function alias exists */
+ if (NULL !== ($tmp = @mysqli_escape_string()))
+ printf("[011] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--EXPECTF--
+Warning: mysqli_real_escape_string(): Couldn't fetch mysqli in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_real_escape_string_big5.phpt b/ext/mysqli/tests/mysqli_real_escape_string_big5.phpt
new file mode 100644
index 0000000..b177c1f
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_real_escape_string_big5.phpt
@@ -0,0 +1,82 @@
+--TEST--
+mysqli_real_escape_string() - big5
+--SKIPIF--
+<?php
+if (ini_get('unicode.semantics'))
+ die("skip Test cannot be run in unicode mode");
+
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+require_once('connect.inc');
+
+if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ die(sprintf("skip Cannot connect to MySQL, [%d] %s\n",
+ mysqli_connect_errno(), mysqli_connect_error()));
+}
+if (!mysqli_set_charset($link, 'big5'))
+ die(sprintf("skip Cannot set charset 'big5'"));
+mysqli_close($link);
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+{
+ printf("[001] Cannot connect to the server using host=%s, user=%s,
+passwd=***, dbname=%s, port=%s, socket=%s - [%d] %s\n", $host, $user, $db,
+$port, $socket, mysqli_connect_errno(), mysqli_connect_error());
+ }
+
+ if (!mysqli_query($link, 'DROP TABLE IF EXISTS test')) {
+ printf("Failed to drop old test table: [%d] %s\n", mysqli_errno($link),
+mysqli_error($link));
+ }
+
+ if (!mysqli_query($link, 'CREATE TABLE test(id INT, label CHAR(1), PRIMARY
+KEY(id)) ENGINE=' . $engine . " DEFAULT CHARSET=big5")) {
+ printf("Failed to create test table: [%d] %s\n", mysqli_errno($link),
+mysqli_error($link));
+ }
+
+ var_dump(mysqli_set_charset($link, "big5"));
+
+ if ('§ä¨ì¥H¤U¤º®e\\\\§ä¨ì¥H¤U¤º®e' !== ($tmp = mysqli_real_escape_string($link,
+'§ä¨ì¥H¤U¤º®e\\§ä¨ì¥H¤U¤º®e')))
+ printf("[004] Expecting \\\\, got %s\n", $tmp);
+
+ if ('§ä¨ì¥H¤U¤º®e\"§ä¨ì¥H¤U¤º®e' !== ($tmp = mysqli_real_escape_string($link,
+'§ä¨ì¥H¤U¤º®e"§ä¨ì¥H¤U¤º®e')))
+ printf("[005] Expecting \", got %s\n", $tmp);
+
+ if ("§ä¨ì¥H¤U¤º®e\'§ä¨ì¥H¤U¤º®e" !== ($tmp = mysqli_real_escape_string($link,
+"§ä¨ì¥H¤U¤º®e'§ä¨ì¥H¤U¤º®e")))
+ printf("[006] Expecting ', got %s\n", $tmp);
+
+ if ("§ä¨ì¥H¤U¤º®e\\n§ä¨ì¥H¤U¤º®e" !== ($tmp = mysqli_real_escape_string($link,
+"§ä¨ì¥H¤U¤º®e\n§ä¨ì¥H¤U¤º®e")))
+ printf("[007] Expecting \\n, got %s\n", $tmp);
+
+ if ("§ä¨ì¥H¤U¤º®e\\r§ä¨ì¥H¤U¤º®e" !== ($tmp = mysqli_real_escape_string($link,
+"§ä¨ì¥H¤U¤º®e\r§ä¨ì¥H¤U¤º®e")))
+ printf("[008] Expecting \\r, got %s\n", $tmp);
+
+ if ("§ä¨ì¥H¤U¤º®e\\0§ä¨ì¥H¤U¤º®e" !== ($tmp = mysqli_real_escape_string($link, "§ä¨ì¥H¤U¤º®e"
+. chr(0) . "§ä¨ì¥H¤U¤º®e")))
+ printf("[009] Expecting %s, got %s\n", "§ä¨ì¥H¤U¤º®e\\0§ä¨ì¥H¤U¤º®e", $tmp);
+
+ var_dump(mysqli_query($link, "INSERT INTO test(id, label) VALUES (100,
+'§ä')"));
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+bool(true)
+bool(true)
+done!
diff --git a/ext/mysqli/tests/mysqli_real_escape_string_eucjpms.phpt b/ext/mysqli/tests/mysqli_real_escape_string_eucjpms.phpt
new file mode 100644
index 0000000..cf4afb6
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_real_escape_string_eucjpms.phpt
@@ -0,0 +1,75 @@
+--TEST--
+mysqli_real_escape_string() - eucjpms
+--SKIPIF--
+<?php
+if (ini_get('unicode.semantics'))
+ die("skip Test cannot be run in unicode mode");
+
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+require_once('connect.inc');
+
+if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ die(sprintf("skip Cannot connect to MySQL, [%d] %s\n",
+ mysqli_connect_errno(), mysqli_connect_error()));
+}
+if (!mysqli_set_charset($link, 'eucjpms'))
+ die(sprintf("skip Cannot set charset 'eucjpms'"));
+mysqli_close($link);
+?>
+--FILE--
+<?php
+require_once("connect.inc");
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+{
+ printf("[001] Cannot connect to the server using host=%s, user=%s,
+passwd=***, dbname=%s, port=%s, socket=%s - [%d] %s\n", $host, $user, $db,
+$port, $socket, mysqli_connect_errno(), mysqli_connect_error());
+ }
+
+ if (!mysqli_query($link, 'DROP TABLE IF EXISTS test')) {
+ printf("Failed to drop old test table: [%d] %s\n", mysqli_errno($link),
+mysqli_error($link));
+ }
+
+ if (!mysqli_query($link, 'CREATE TABLE test(id INT, label CHAR(1), PRIMARY
+KEY(id)) ENGINE=' . $engine . " DEFAULT CHARSET=eucjpms")) {
+ printf("Failed to create test table: [%d] %s\n", mysqli_errno($link),
+mysqli_error($link));
+ }
+
+ var_dump(mysqli_set_charset($link, "eucjpms"));
+
+ if ('¤³¤ÎÁȤ߹ç¤ï¤»¤Ç¤Ï\\\\¤³¤ÎÁȤ߹ç¤ï¤»¤Ç¤Ï' !== ($tmp = mysqli_real_escape_string($link, '¤³¤ÎÁȤ߹ç¤ï¤»¤Ç¤Ï\\¤³¤ÎÁȤ߹ç¤ï¤»¤Ç¤Ï')))
+ printf("[004] Expecting \\\\, got %s\n", $tmp);
+
+ if ('¤³¤ÎÁȤ߹ç¤ï¤»¤Ç¤Ï\"¤³¤ÎÁȤ߹ç¤ï¤»¤Ç¤Ï' !== ($tmp = mysqli_real_escape_string($link, '¤³¤ÎÁȤ߹ç¤ï¤»¤Ç¤Ï"¤³¤ÎÁȤ߹ç¤ï¤»¤Ç¤Ï')))
+ printf("[005] Expecting \", got %s\n", $tmp);
+
+ if ("¤³¤ÎÁȤ߹ç¤ï¤»¤Ç¤Ï\'¤³¤ÎÁȤ߹ç¤ï¤»¤Ç¤Ï" !== ($tmp = mysqli_real_escape_string($link, "¤³¤ÎÁȤ߹ç¤ï¤»¤Ç¤Ï'¤³¤ÎÁȤ߹ç¤ï¤»¤Ç¤Ï")))
+ printf("[006] Expecting ', got %s\n", $tmp);
+
+ if ("¤³¤ÎÁȤ߹ç¤ï¤»¤Ç¤Ï\\n¤³¤ÎÁȤ߹ç¤ï¤»¤Ç¤Ï" !== ($tmp = mysqli_real_escape_string($link, "¤³¤ÎÁȤ߹ç¤ï¤»¤Ç¤Ï\n¤³¤ÎÁȤ߹ç¤ï¤»¤Ç¤Ï")))
+ printf("[007] Expecting \\n, got %s\n", $tmp);
+
+ if ("¤³¤ÎÁȤ߹ç¤ï¤»¤Ç¤Ï\\r¤³¤ÎÁȤ߹ç¤ï¤»¤Ç¤Ï" !== ($tmp = mysqli_real_escape_string($link, "¤³¤ÎÁȤ߹ç¤ï¤»¤Ç¤Ï\r¤³¤ÎÁȤ߹ç¤ï¤»¤Ç¤Ï")))
+ printf("[008] Expecting \\r, got %s\n", $tmp);
+
+ if ("¤³¤ÎÁȤ߹ç¤ï¤»¤Ç¤Ï\\0¤³¤ÎÁȤ߹ç¤ï¤»¤Ç¤Ï" !== ($tmp = mysqli_real_escape_string($link, "¤³¤ÎÁȤ߹ç¤ï¤»¤Ç¤Ï" . chr(0) . "¤³¤ÎÁȤ߹ç¤ï¤»¤Ç¤Ï")))
+ printf("[009] Expecting %s, got %s\n", "¤³¤ÎÁȤ߹ç¤ï¤»¤Ç¤Ï\\0¤³¤ÎÁȤ߹ç¤ï¤»¤Ç¤Ï", $tmp);
+
+ var_dump(mysqli_query($link, "INSERT INTO test(id, label) VALUES (100, '¤³')"));
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+bool(true)
+bool(true)
+done!
diff --git a/ext/mysqli/tests/mysqli_real_escape_string_euckr.phpt b/ext/mysqli/tests/mysqli_real_escape_string_euckr.phpt
new file mode 100644
index 0000000..7ac7497
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_real_escape_string_euckr.phpt
@@ -0,0 +1,74 @@
+--TEST--
+mysqli_real_escape_string() - euckr
+--SKIPIF--
+<?php
+if (ini_get('unicode.semantics'))
+ die("skip Test cannot be run in unicode mode");
+
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+require_once('connect.inc');
+
+if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ die(sprintf("skip Cannot connect to MySQL, [%d] %s\n",
+ mysqli_connect_errno(), mysqli_connect_error()));
+}
+if (!mysqli_set_charset($link, 'euckr'))
+ die(sprintf("skip Cannot set charset 'euckr'"));
+mysqli_close($link);
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+{
+ printf("[001] Cannot connect to the server using host=%s, user=%s,
+passwd=***, dbname=%s, port=%s, socket=%s - [%d] %s\n", $host, $user, $db,
+$port, $socket, mysqli_connect_errno(), mysqli_connect_error());
+ }
+
+ if (!mysqli_query($link, 'DROP TABLE IF EXISTS test')) {
+ printf("Failed to drop old test table: [%d] %s\n", mysqli_errno($link),
+mysqli_error($link));
+ }
+
+ if (!mysqli_query($link, 'CREATE TABLE test(id INT, label CHAR(1), PRIMARY
+KEY(id)) ENGINE=' . $engine . " DEFAULT CHARSET=euckr")) {
+ printf("Failed to create test table: [%d] %s\n", mysqli_errno($link),
+mysqli_error($link));
+ }
+
+ var_dump(mysqli_set_charset($link, "euckr"));
+
+ if ('±Ç´ë¼º\\\\±Ç´ë¼º' !== ($tmp = mysqli_real_escape_string($link, '±Ç´ë¼º\\±Ç´ë¼º')))
+ printf("[004] Expecting \\\\, got %s\n", $tmp);
+
+ if ('±Ç´ë¼º\"±Ç´ë¼º' !== ($tmp = mysqli_real_escape_string($link, '±Ç´ë¼º"±Ç´ë¼º')))
+ printf("[005] Expecting \", got %s\n", $tmp);
+
+ if ("±Ç´ë¼º\'±Ç´ë¼º" !== ($tmp = mysqli_real_escape_string($link, "±Ç´ë¼º'±Ç´ë¼º")))
+ printf("[006] Expecting ', got %s\n", $tmp);
+
+ if ("±Ç´ë¼º\\n±Ç´ë¼º" !== ($tmp = mysqli_real_escape_string($link, "±Ç´ë¼º\n±Ç´ë¼º")))
+ printf("[007] Expecting \\n, got %s\n", $tmp);
+
+ if ("±Ç´ë¼º\\r±Ç´ë¼º" !== ($tmp = mysqli_real_escape_string($link, "±Ç´ë¼º\r±Ç´ë¼º")))
+ printf("[008] Expecting \\r, got %s\n", $tmp);
+
+ if ("±Ç´ë¼º\\0±Ç´ë¼º" !== ($tmp = mysqli_real_escape_string($link, "±Ç´ë¼º" . chr(0) . "±Ç´ë¼º")))
+ printf("[009] Expecting %s, got %s\n", "±Ç´ë¼º\\0±Ç´ë¼º", $tmp);
+
+ var_dump(mysqli_query($link, "INSERT INTO test(id, label) VALUES (100, '±Ç')"));
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+bool(true)
+bool(true)
+done!
diff --git a/ext/mysqli/tests/mysqli_real_escape_string_gb2312.phpt b/ext/mysqli/tests/mysqli_real_escape_string_gb2312.phpt
new file mode 100644
index 0000000..b93d815
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_real_escape_string_gb2312.phpt
@@ -0,0 +1,75 @@
+--TEST--
+mysqli_real_escape_string() - gb2312
+--SKIPIF--
+<?php
+if (ini_get('unicode.semantics'))
+ die("skip Test cannot be run in unicode mode");
+
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+require_once('connect.inc');
+
+if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ die(sprintf("skip Cannot connect to MySQL, [%d] %s\n",
+ mysqli_connect_errno(), mysqli_connect_error()));
+}
+if (!mysqli_set_charset($link, 'gb2312'))
+ die(sprintf("skip Cannot set charset 'gb2312'"));
+mysqli_close($link);
+?>
+--FILE--
+<?php
+
+ require_once("connect.inc");
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+{
+ printf("[001] Cannot connect to the server using host=%s, user=%s,
+passwd=***, dbname=%s, port=%s, socket=%s - [%d] %s\n", $host, $user, $db,
+$port, $socket, mysqli_connect_errno(), mysqli_connect_error());
+ }
+
+ if (!mysqli_query($link, 'DROP TABLE IF EXISTS test')) {
+ printf("Failed to drop old test table: [%d] %s\n", mysqli_errno($link),
+mysqli_error($link));
+ }
+
+ if (!mysqli_query($link, 'CREATE TABLE test(id INT, label CHAR(1), PRIMARY
+KEY(id)) ENGINE=' . $engine . " DEFAULT CHARSET=gb2312")) {
+ printf("Failed to create test table: [%d] %s\n", mysqli_errno($link),
+mysqli_error($link));
+ }
+
+ var_dump(mysqli_set_charset($link, "gb2312"));
+
+ if ('Ê×ÏÈ\\\\Ê×ÏÈ' !== ($tmp = mysqli_real_escape_string($link, 'Ê×ÏÈ\\Ê×ÏÈ')))
+ printf("[004] Expecting \\\\, got %s\n", $tmp);
+
+ if ('Ê×ÏÈ\"Ê×ÏÈ' !== ($tmp = mysqli_real_escape_string($link, 'Ê×ÏÈ"Ê×ÏÈ')))
+ printf("[005] Expecting \", got %s\n", $tmp);
+
+ if ("Ê×ÏÈ\'Ê×ÏÈ" !== ($tmp = mysqli_real_escape_string($link, "Ê×ÏÈ'Ê×ÏÈ")))
+ printf("[006] Expecting ', got %s\n", $tmp);
+
+ if ("Ê×ÏÈ\\nÊ×ÏÈ" !== ($tmp = mysqli_real_escape_string($link, "Ê×ÏÈ\nÊ×ÏÈ")))
+ printf("[007] Expecting \\n, got %s\n", $tmp);
+
+ if ("Ê×ÏÈ\\rÊ×ÏÈ" !== ($tmp = mysqli_real_escape_string($link, "Ê×ÏÈ\rÊ×ÏÈ")))
+ printf("[008] Expecting \\r, got %s\n", $tmp);
+
+ if ("Ê×ÏÈ\\0Ê×ÏÈ" !== ($tmp = mysqli_real_escape_string($link, "Ê×ÏÈ" . chr(0) . "Ê×ÏÈ")))
+ printf("[009] Expecting %s, got %s\n", "Ê×ÏÈ\\0Ê×ÏÈ", $tmp);
+
+ var_dump(mysqli_query($link, "INSERT INTO test(id, label) VALUES (100, 'Ê×')"));
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+bool(true)
+bool(true)
+done!
diff --git a/ext/mysqli/tests/mysqli_real_escape_string_gbk.phpt b/ext/mysqli/tests/mysqli_real_escape_string_gbk.phpt
new file mode 100644
index 0000000..2fd1121
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_real_escape_string_gbk.phpt
@@ -0,0 +1,77 @@
+--TEST--
+mysqli_real_escape_string() - gbk
+--SKIPIF--
+<?php
+if (version_compare(PHP_VERSION, '5.9.9', '>') == 1) {
+ die('skip set character set not functional with PHP 6 (fomerly PHP 6 && unicode.semantics=On)');
+}
+
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+require_once('connect.inc');
+
+if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ die(sprintf("skip Cannot connect to MySQL, [%d] %s\n",
+ mysqli_connect_errno(), mysqli_connect_error()));
+}
+if (!mysqli_set_charset($link, 'gbk'))
+ die(sprintf("skip Cannot set charset 'gbk'"));
+
+mysqli_close($link);
+?>
+--FILE--
+<?php
+
+ require_once("connect.inc");
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+{
+ printf("[001] Cannot connect to the server using host=%s, user=%s,
+passwd=***, dbname=%s, port=%s, socket=%s - [%d] %s\n", $host, $user, $db,
+$port, $socket, mysqli_connect_errno(), mysqli_connect_error());
+ }
+
+ if (!mysqli_query($link, 'DROP TABLE IF EXISTS test')) {
+ printf("Failed to drop old test table: [%d] %s\n", mysqli_errno($link),
+mysqli_error($link));
+ }
+
+ if (!mysqli_query($link, 'CREATE TABLE test(id INT, label CHAR(1), PRIMARY
+KEY(id)) ENGINE=' . $engine . " DEFAULT CHARSET=gbk")) {
+ printf("Failed to create test table: [%d] %s\n", mysqli_errno($link),
+mysqli_error($link));
+ }
+
+ var_dump(mysqli_set_charset($link, "gbk"));
+
+ if ('�İ汾\\\\�İ汾' !== ($tmp = mysqli_real_escape_string($link, '�İ汾\\�İ汾')))
+ printf("[004] Expecting \\\\, got %s\n", $tmp);
+
+ if ('�İ汾\"�İ汾' !== ($tmp = mysqli_real_escape_string($link, '�İ汾"�İ汾')))
+ printf("[005] Expecting \", got %s\n", $tmp);
+
+ if ("�İ汾\'�İ汾" !== ($tmp = mysqli_real_escape_string($link, "�İ汾'�İ汾")))
+ printf("[006] Expecting ', got %s\n", $tmp);
+
+ if ("�İ汾\\n�İ汾" !== ($tmp = mysqli_real_escape_string($link, "�İ汾\n�İ汾")))
+ printf("[007] Expecting \\n, got %s\n", $tmp);
+
+ if ("�İ汾\\r�İ汾" !== ($tmp = mysqli_real_escape_string($link, "�İ汾\r�İ汾")))
+ printf("[008] Expecting \\r, got %s\n", $tmp);
+
+ if ("�İ汾\\0�İ汾" !== ($tmp = mysqli_real_escape_string($link, "�İ汾" . chr(0) . "�İ汾")))
+ printf("[009] Expecting %s, got %s\n", "�İ汾\\0�İ汾", $tmp);
+
+ var_dump(mysqli_query($link, "INSERT INTO test(id, label) VALUES (100, '��')"));
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+bool(true)
+bool(true)
+done!
diff --git a/ext/mysqli/tests/mysqli_real_escape_string_nobackslash.phpt b/ext/mysqli/tests/mysqli_real_escape_string_nobackslash.phpt
new file mode 100644
index 0000000..db1acb4
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_real_escape_string_nobackslash.phpt
@@ -0,0 +1,65 @@
+--TEST--
+mysqli_real_escape_string() - SQL Mode NO_BACKSLASH_ESCAPE
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+ require_once('table.inc');
+
+ if (!mysqli_query($link, 'SET @@sql_mode="NO_BACKSLASH_ESCAPES"'))
+ printf("[001] Cannot set NO_BACKSLASH_ESCAPES, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if ('\\' !== ($tmp = mysqli_real_escape_string($link, '\\')))
+ printf("[002] Expecting \\, got %s\n", $tmp);
+
+ if ('"' !== ($tmp = mysqli_real_escape_string($link, '"')))
+ printf("[003] Expecting \", got %s\n", $tmp);
+
+ if ("''" !== ($tmp = mysqli_real_escape_string($link, "'")))
+ printf("[004] Expecting '', got %s\n", $tmp);
+
+ if ("\n" !== ($tmp = mysqli_real_escape_string($link, "\n")))
+ printf("[005] Expecting \\n, got %s\n", $tmp);
+
+ if ("\r" !== ($tmp = mysqli_real_escape_string($link, "\r")))
+ printf("[006] Expecting \\r, got %s\n", $tmp);
+
+ assert("foo" . chr(0) . "bar" === "foo" . chr(0) . "bar");
+ if ("foo" . chr(0) . "bar" !== ($tmp = mysqli_real_escape_string($link, "foo" . chr(0) . "bar")))
+ printf("[007] Expecting %s, got %s\n", "foo" . chr(0) . "bar", $tmp);
+
+ if (!mysqli_query($link, sprintf('INSERT INTO test(id, label) VALUES (100, "%s")',
+ mysqli_real_escape_string($link, "\\"))))
+ printf("[009] Cannot INSERT, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!($res = mysqli_query($link, 'SELECT label FROM test WHERE id = 100')) ||
+ !($row = mysqli_fetch_assoc($res)))
+ printf("[010] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ var_dump($row);
+ mysqli_free_result($res);
+
+ if (!mysqli_query($link, 'SET @@sql_mode=""'))
+ printf("[011] Cannot disable NO_BACKSLASH_ESCAPES, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if ('\\\\' !== ($tmp = mysqli_real_escape_string($link, '\\')))
+ printf("[012] Expecting \\, got %s\n", $tmp);
+
+ if ("foo\\0bar" !== ($tmp = mysqli_real_escape_string($link, "foo" . chr(0) . "bar")))
+ printf("[013] Expecting %s, got %s\n", "foo" . chr(0) . "bar", $tmp);
+
+ mysqli_close($link);
+
+ print "done!";
+?>
+--EXPECTF--
+array(1) {
+ [%u|b%"label"]=>
+ %unicode|string%(1) "\"
+}
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_real_escape_string_sjis.phpt b/ext/mysqli/tests/mysqli_real_escape_string_sjis.phpt
new file mode 100644
index 0000000..2ed2b8b
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_real_escape_string_sjis.phpt
@@ -0,0 +1,56 @@
+--TEST--
+mysqli_real_escape_string() - sjis
+--SKIPIF--
+<?php
+if (version_compare(PHP_VERSION, '5.9.9', '>') == 1) {
+ die('skip set character set not functional with PHP 6 (fomerly PHP 6 && unicode.semantics=On)');
+}
+
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+require_once('connect.inc');
+
+if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ die(sprintf("skip Cannot connect to MySQL, [%d] %s\n",
+ mysqli_connect_errno(), mysqli_connect_error()));
+}
+if (!mysqli_set_charset($link, 'sjis'))
+ die(sprintf("skip Cannot set charset 'sjis'"));
+mysqli_close($link);
+?>
+--FILE--
+<?php
+
+ require_once("connect.inc");
+ require_once('table.inc');
+
+ var_dump(mysqli_set_charset($link, "sjis"));
+
+ if ('?p??\\\\?p??' !== ($tmp = mysqli_real_escape_string($link, '?p??\\?p??')))
+ printf("[004] Expecting \\\\, got %s\n", $tmp);
+
+ if ('?p??\"?p??' !== ($tmp = mysqli_real_escape_string($link, '?p??"?p??')))
+ printf("[005] Expecting \", got %s\n", $tmp);
+
+ if ("?p??\'?p??" !== ($tmp = mysqli_real_escape_string($link, "?p??'?p??")))
+ printf("[006] Expecting ', got %s\n", $tmp);
+
+ if ("?p??\\n?p??" !== ($tmp = mysqli_real_escape_string($link, "?p??\n?p??")))
+ printf("[007] Expecting \\n, got %s\n", $tmp);
+
+ if ("?p??\\r?p??" !== ($tmp = mysqli_real_escape_string($link, "?p??\r?p??")))
+ printf("[008] Expecting \\r, got %s\n", $tmp);
+
+ if ("?p??\\0?p??" !== ($tmp = mysqli_real_escape_string($link, "?p??" . chr(0) . "?p??")))
+ printf("[009] Expecting %s, got %s\n", "?p??\\0?p??", $tmp);
+
+ var_dump(mysqli_query($link, "INSERT INTO test(id, label) VALUES (100, '?p')"));
+
+ mysqli_close($link);
+ print "done!";
+?>
+--EXPECTF--
+bool(true)
+bool(true)
+done!
diff --git a/ext/mysqli/tests/mysqli_real_escape_string_unicode.phpt b/ext/mysqli/tests/mysqli_real_escape_string_unicode.phpt
new file mode 100644
index 0000000..72d171f
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_real_escape_string_unicode.phpt
@@ -0,0 +1,88 @@
+--TEST--
+mysqli_real_escape_string()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (NULL !== ($tmp = @mysqli_real_escape_string()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (NULL !== ($tmp = @mysqli_real_escape_string($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (NULL !== ($tmp =@mysqli_real_escape_string($link, "фуу", "бар")))
+ printf("[003] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if ('фу\\\\бар' !== ($tmp = mysqli_real_escape_string($link, 'фу\\бар')))
+ printf("[004] Expecting фу\\\\бар, got %s\n", $tmp);
+
+ if ('бар\"фуÑ' !== ($tmp = mysqli_real_escape_string($link, 'бар"фуÑ')))
+ printf("[005] Expecting бар\"фуÑ, got %s\n", $tmp);
+
+ if ("лала\'лали" !== ($tmp = mysqli_real_escape_string($link, "лала'лали")))
+ printf("[006] Expecting лала'лали, got %s\n", $tmp);
+
+ if ("абра\\nкадабра" !== ($tmp = mysqli_real_escape_string($link, "абра\nкадабра")))
+ printf("[007] Expecting абра\\nкадабра, got %s\n", $tmp);
+
+ if ("манда\\rин" !== ($tmp = mysqli_real_escape_string($link, "манда\rин")))
+ printf("[008] Expecting \\r, got %s\n", $tmp);
+
+ if ("иху\\0аху" !== ($tmp = mysqli_real_escape_string($link, "иху" . chr(0) . "аху")))
+ printf("[009] Expecting %s, got %s\n", "иху\\0аху", $tmp);
+
+ if (($exp='абра\\\\ка\"да\\'."'".'бра\ZÑим\\nÑала\\rби\\0м') !==
+ ($tmp = mysqli_real_escape_string($link, "абра\\ка\"да'бра\032Ñим\nÑала\rби" . chr(0) . "м")))
+ {
+ printf("[010] Expecting %s, got %s\n", $exp, $tmp, var_dump($exp, $tmp));
+ }
+
+ if ('富\\\\é…’å§' !== ($tmp = mysqli_real_escape_string($link, '富\\é…’å§')))
+ printf("[011] Expecting 富\\\\é…’å§, got %s\n", $tmp);
+
+ if ('é…’å§\"å°é¢˜å¤§åš' !== ($tmp = mysqli_real_escape_string($link, 'é…’å§"å°é¢˜å¤§åš')))
+ printf("[012] Expecting é…’å§\"å°é¢˜å¤§åš, got %s\n", $tmp);
+
+ if ("拉拉\'西雅图" !== ($tmp = mysqli_real_escape_string($link, "拉拉'西雅图")))
+ printf("[013] Expecting 拉拉'西雅图, got %s\n", $tmp);
+
+ if ("é˜¿åœæ‹‰\\nè½»" !== ($tmp = mysqli_real_escape_string($link, "é˜¿åœæ‹‰\nè½»")))
+ printf("[014] Expecting é˜¿åœæ‹‰\\nè½», got %s\n", $tmp);
+
+ if ("张明安\\r在" !== ($tmp = mysqli_real_escape_string($link, "张明安\r在")))
+ printf("[015] Expecting 张明安\\r在, got %s\n", $tmp);
+
+ if ("ç«ºå¯æ¡¢\\0空调器" !== ($tmp = mysqli_real_escape_string($link, "ç«ºå¯æ¡¢" . chr(0) . "空调器")))
+ printf("[016] Expecting %s, got %s\n", "ç«ºå¯æ¡¢\\0空调器", $tmp);
+
+ if (($exp='é˜¿åœæ‹‰\\\\嘉\"达丰\\'."'".'乳罩\Zè¾›\\nè¨æ‹‰\\r毕\\0ç±³') !==
+ ($tmp = mysqli_real_escape_string($link, "é˜¿åœæ‹‰\\嘉\"达丰'乳罩\032è¾›\nè¨æ‹‰\r毕" . chr(0) . "ç±³")))
+ {
+ printf("[017] Expecting %s, got %s\n", $exp, $tmp, var_dump($exp, $tmp));
+ }
+
+ mysqli_close($link);
+
+ if (NULL !== ($tmp = mysqli_real_escape_string($link, 'foo')))
+ printf("[018] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Warning: mysqli_real_escape_string(): Couldn't fetch mysqli in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_real_query.phpt b/ext/mysqli/tests/mysqli_real_query.phpt
new file mode 100644
index 0000000..866ad6a
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_real_query.phpt
@@ -0,0 +1,113 @@
+--TEST--
+mysqli_real_query()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_real_query()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_real_query($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (NULL !== ($tmp = @mysqli_real_query($link, "SELECT 1 AS a", MYSQLI_USE_RESULT, "foo")))
+ printf("[003] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (false !== ($tmp = mysqli_real_query($link, 'THIS IS NOT SQL')))
+ printf("[004] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (false !== ($tmp = mysqli_real_query($link, "SELECT 'this is sql but with backslash g'\g")))
+ printf("[005] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if ((0 === mysqli_errno($link)) || ('' == mysqli_error($link)))
+ printf("[006] mysqli_errno()/mysqli_error should return some error\n");
+
+ if (!mysqli_real_query($link, "SELECT 'this is sql but with semicolon' AS valid ; "))
+ printf("[007] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!is_object($res = mysqli_use_result($link)))
+ printf("[008] Expecting reseult object, got %s/%s [%d] %s\n", gettype($res), $res, mysqli_errno($link), mysqli_error($link));
+
+ var_dump(mysqli_fetch_assoc($res));
+ mysqli_free_result($res);
+
+ if (false !== ($res = mysqli_real_query($link, "SELECT 'this is sql but with semicolon' AS valid ; SHOW VARIABLES")))
+ printf("[008] Expecting boolean/false, got %s/%s, [%d] %s\n", gettype($res), $res,
+ mysqli_errno($link), mysqli_error($link));
+
+ if (mysqli_get_server_version($link) > 50000) {
+ // let's try to play with stored procedures
+ mysqli_real_query($link, 'DROP PROCEDURE IF EXISTS p');
+ if (mysqli_real_query($link, 'CREATE PROCEDURE p(OUT ver_param VARCHAR(25)) BEGIN SELECT VERSION() INTO ver_param;
+END;')) {
+ mysqli_real_query($link, 'CALL p(@version)');
+ mysqli_real_query($link, 'SELECT @version AS p_version');
+ $res = mysqli_store_result($link);
+
+ $tmp = mysqli_fetch_assoc($res);
+ if (!is_array($tmp) || empty($tmp) || !isset($tmp['p_version']) || ('' == $tmp['p_version'])) {
+ printf("[008a] Expecting array [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ var_dump($tmp);
+ }
+
+ mysqli_free_result($res);
+ } else {
+ printf("[009] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+ mysqli_real_query($link, 'DROP FUNCTION IF EXISTS f');
+ if (mysqli_real_query($link, 'CREATE FUNCTION f( ver_param VARCHAR(25)) RETURNS VARCHAR(25) DETERMINISTIC RETURN
+ver_param;')) {
+ mysqli_real_query($link, 'SELECT f(VERSION()) AS f_version');
+ $res = mysqli_store_result($link);
+
+ $tmp = mysqli_fetch_assoc($res);
+ if (!is_array($tmp) || empty($tmp) || !isset($tmp['f_version']) || ('' == $tmp['f_version'])) {
+ printf("[009a] Expecting array [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ var_dump($tmp);
+ }
+
+ mysqli_free_result($res);
+ } else {
+ printf("[010] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+ }
+
+ mysqli_close($link);
+
+ if (NULL !== ($tmp = mysqli_real_query($link, "SELECT id FROM test")))
+ printf("[011] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS test"))
+ printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+@mysqli_query($link, "DROP PROCEDURE IF EXISTS p");
+@mysqli_query($link, "DROP FUNCTION IF EXISTS f");
+
+mysqli_close($link);
+?>
+--EXPECTF--
+array(1) {
+ [%u|b%"valid"]=>
+ %unicode|string%(30) "this is sql but with semicolon"
+}
+
+Warning: mysqli_real_query(): Couldn't fetch mysqli in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_reconnect.phpt b/ext/mysqli/tests/mysqli_reconnect.phpt
new file mode 100644
index 0000000..7f05a20
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_reconnect.phpt
@@ -0,0 +1,130 @@
+--TEST--
+Trying implicit reconnect after wait_timeout and KILL using mysqli_ping()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+if (stristr(mysqli_get_client_info(), 'mysqlnd'))
+ die("skip: test for libmysql");
+?>
+--INI--
+mysqli.reconnect=1
+--FILE--
+<?php
+ require_once("connect.inc");
+ require_once("table.inc");
+
+ if (!$link2 = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[001] Cannot create second database connection, [%d] %s\n",
+ mysqli_connect_errno(), mysqli_connect_error());
+
+ $thread_id_timeout = mysqli_thread_id($link);
+ $thread_id_control = mysqli_thread_id($link2);
+
+ if (!$res = mysqli_query($link2, "SHOW FULL PROCESSLIST"))
+ printf("[002] Cannot get full processlist, [%d] %s\n",
+ mysqli_errno($link2), mysqli_error($link));
+
+ $running_threads = array();
+ while ($row = mysqli_fetch_assoc($res))
+ $running_threads[$row['Id']] = $row;
+ mysqli_free_result($res);
+
+ if (!isset($running_threads[$thread_id_timeout]) ||
+ !isset($running_threads[$thread_id_control]))
+ printf("[003] Processlist is borked, [%d] %s\n",
+ mysqli_errno($link2), mysqli_error($link));
+
+ if (!mysqli_query($link, "SET SESSION wait_timeout = 2"))
+ printf("[004] Cannot set wait_timeout, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$res = mysqli_query($link, "SHOW VARIABLES LIKE 'wait_timeout'"))
+ printf("[005] Cannot check if wait_timeout has been set, [%d] %s\n",
+ mysqli_errno($link), mysqli_error($link));
+
+ if (!$row = mysqli_fetch_assoc($res))
+ printf("[006] Cannot get wait_timeout, [%d] %s\n",
+ mysqli_errno($link), mysqli_error($link));
+ mysqli_free_result($res);
+
+ if ($row['Value'] != 2)
+ printf("[007] Failed setting the wait_timeout, test will not work, [%d] %s\n",
+ mysqli_errno($link), mysqli_error($link));
+
+ // after 2+ seconds the server should kill the connection
+ sleep(3);
+
+ if (!$res = mysqli_query($link2, "SHOW FULL PROCESSLIST"))
+ printf("[008] Cannot get full processlist, [%d] %s\n",
+ mysqli_errno($link2), mysqli_error($link));
+
+ $running_threads = array();
+ while ($row = mysqli_fetch_assoc($res))
+ $running_threads[$row['Id']] = $row;
+ mysqli_free_result($res);
+
+ if (isset($running_threads[$thread_id_timeout]))
+ printf("[009] Server should have killed the timeout connection, [%d] %s\n",
+ mysqli_errno($link2), mysqli_error($link));
+
+ if (true !== mysqli_ping($link))
+ printf("[010] Reconnect should have happened");
+
+ if (!$res = mysqli_query($link, "SELECT DATABASE() as _dbname"))
+ printf("[011] Cannot get database name, [%d] %s\n",
+ mysqli_errno($link), mysqli_error($link));
+
+ if (!$row = mysqli_fetch_assoc($res))
+ printf("[012] Cannot get database name, [%d] %s\n",
+ mysqli_errno($link), mysqli_error($link));
+
+ mysqli_free_result($res);
+ if ($row['_dbname'] != $db)
+ printf("[013] Connection should has been made to DB/Schema '%s', expecting '%s', [%d] %s\n",
+ $row['_dbname'], $db, mysqli_errno($link), mysqli_error($link));
+
+ // ... and now we try KILL
+ $thread_id_timeout = mysqli_thread_id($link);
+
+ if (!mysqli_query($link2, sprintf('KILL %d', $thread_id_timeout)))
+ printf("[014] Cannot KILL timeout connection, [%d] %s\n", mysqli_errno($link2), mysqli_error($link2));
+ // Give the server a second to really kill the other thread...
+ sleep(1);
+
+ if (!$res = mysqli_query($link2, "SHOW FULL PROCESSLIST"))
+ printf("[015] Cannot get full processlist, [%d] %s\n",
+ mysqli_errno($link2), mysqli_error($link));
+
+ $running_threads = array();
+ while ($row = mysqli_fetch_assoc($res))
+ $running_threads[$row['Id']] = $row;
+ mysqli_free_result($res);
+
+ if (isset($running_threads[$thread_id_timeout]) ||
+ !isset($running_threads[$thread_id_control]))
+ printf("[016] Processlist is borked, [%d] %s\n",
+ mysqli_errno($link2), mysqli_error($link));
+
+ if (true !== ($tmp = mysqli_ping($link)))
+ printf("[017] Expecting boolean/true got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$res = mysqli_query($link, "SELECT DATABASE() as _dbname"))
+ printf("[018] Cannot get database name, [%d] %s\n",
+ mysqli_errno($link), mysqli_error($link));
+
+ if (!$row = mysqli_fetch_assoc($res))
+ printf("[019] Cannot get database name, [%d] %s\n",
+ mysqli_errno($link), mysqli_error($link));
+
+ mysqli_free_result($res);
+ if ($row['_dbname'] != $db)
+ printf("[020] Connection should has been made to DB/Schema '%s', expecting '%s', [%d] %s\n",
+ $row['_dbname'], $db, mysqli_errno($link), mysqli_error($link));
+
+ mysqli_close($link);
+ mysqli_close($link2);
+ print "done!";
+?>
+--EXPECTF--
+done!
diff --git a/ext/mysqli/tests/mysqli_report.phpt b/ext/mysqli/tests/mysqli_report.phpt
new file mode 100644
index 0000000..f5d77e3
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_report.phpt
@@ -0,0 +1,307 @@
+--TEST--
+mysqli_report()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (NULL !== ($tmp = @mysqli_report()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (true !== ($tmp = mysqli_report(-1)))
+ printf("[002] Expecting boolean/true even for invalid flags, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (true !== ($tmp = mysqli_report(MYSQLI_REPORT_ERROR)))
+ printf("[003] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (true !== ($tmp = mysqli_report(MYSQLI_REPORT_STRICT)))
+ printf("[004] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (true !== ($tmp = mysqli_report(MYSQLI_REPORT_INDEX)))
+ printf("[005] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (true !== ($tmp = mysqli_report(MYSQLI_REPORT_ALL)))
+ printf("[007] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (true !== ($tmp = mysqli_report(MYSQLI_REPORT_OFF)))
+ printf("[008] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ /*
+ Internal macro MYSQL_REPORT_ERROR
+ */
+ mysqli_report(MYSQLI_REPORT_ERROR);
+
+ mysqli_multi_query($link, "BAR; FOO;");
+ mysqli_query($link, "FOO");
+ /* This might work if you accept anonymous users in your setup */
+ mysqli_change_user($link, "0123456789-10-456789-20-456789-30-456789-40-456789-50-456789-60-456789-70-456789-80-456789-90-456789", "password", $db);
+ mysqli_kill($link, -1);
+
+ // mysqli_ping() cannot be tested, because one would need to cause an error inside the C function to test it
+ mysqli_prepare($link, "FOO");
+ mysqli_real_query($link, "FOO");
+ if (@mysqli_select_db($link, "Oh lord, let this be an unknown database name"))
+ printf("[009] select_db should have failed\n");
+ // mysqli_store_result() and mysqli_use_result() cannot be tested, because one would need to cause an error inside the C function to test it
+
+
+ // Check that none of the above would have caused any error messages if MYSQL_REPORT_ERROR would
+ // not have been set. If that would be the case, the test would be broken.
+ mysqli_report(MYSQLI_REPORT_OFF);
+
+ mysqli_multi_query($link, "BAR; FOO;");
+ mysqli_query($link, "FOO");
+ mysqli_change_user($link, "This might work if you accept anonymous users in your setup", "password", $db);
+ mysqli_kill($link, -1);
+ mysqli_prepare($link, "FOO");
+ mysqli_real_query($link, "FOO");
+ mysqli_select_db($link, "Oh lord, let this be an unknown database name");
+
+ /*
+ Internal macro MYSQL_REPORT_STMT_ERROR
+ */
+
+ mysqli_report(MYSQLI_REPORT_ERROR);
+
+ $stmt = mysqli_stmt_init($link);
+ mysqli_stmt_prepare($stmt, "FOO");
+
+ $stmt = mysqli_stmt_init($link);
+ mysqli_stmt_prepare($stmt, "SELECT id FROM test WHERE id > ?");
+ $id = 1;
+ mysqli_kill($link, mysqli_thread_id($link));
+ mysqli_stmt_bind_param($stmt, "i", $id);
+ mysqli_stmt_close($stmt);
+ mysqli_close($link);
+
+ /* mysqli_stmt_execute() = mysql_stmt_execute cannot be tested from PHP */
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[008] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+ $stmt = mysqli_stmt_init($link);
+ mysqli_stmt_prepare($stmt, "SELECT id FROM test WHERE id > ?");
+ $id = 1;
+ mysqli_stmt_bind_param($stmt, "i", $id);
+ // mysqli_kill($link, mysqli_thread_id($link));
+ mysqli_stmt_execute($stmt);
+ mysqli_stmt_close($stmt);
+ mysqli_close($link);
+
+ /* mysqli_kill() "trick" does not work for any of the following because of an E_COMMANDS_OUT_OF_SYNC */
+ /* mysqli_stmt_bind_result() = mysql_stmt_bind_result() cannot be tested from PHP */
+ /* mysqli_stmt_fetch() = mysql_stmt_fetch() cannot be tested from PHP */
+ /* mysqli_stmt_result_metadata() = mysql_stmt_result_metadata() cannot be tested from PHP */
+ /* mysqli_stmt_store_result() = mysql_stmt_store_result() cannot be tested from PHP */
+
+ // Check
+ mysqli_report(MYSQLI_REPORT_OFF);
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[010] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+ $stmt = mysqli_stmt_init($link);
+ mysqli_stmt_prepare($stmt, "FOO");
+
+ $stmt = mysqli_stmt_init($link);
+ mysqli_stmt_prepare($stmt, "SELECT id FROM test WHERE id > ?");
+ $id = 1;
+ mysqli_kill($link, mysqli_thread_id($link));
+ mysqli_stmt_bind_param($stmt, "i", $id);
+ mysqli_stmt_close($stmt);
+ mysqli_close($link);
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[011] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+ $stmt = mysqli_stmt_init($link);
+ mysqli_stmt_prepare($stmt, "SELECT id FROM test WHERE id > ?");
+ $id = 1;
+ mysqli_stmt_bind_param($stmt, "i", $id);
+ mysqli_kill($link, mysqli_thread_id($link));
+ mysqli_stmt_execute($stmt);
+ mysqli_stmt_close($stmt);
+ mysqli_close($link);
+
+ /*
+ MYSQLI_REPORT_STRICT
+
+ MYSQLI_REPORT_STRICT --->
+ php_mysqli_report_error() ->
+ MYSQLI_REPORT_MYSQL_ERROR,
+ MYSQLI_REPORT_STMT_ERROR ->
+ already tested
+
+ php_mysqli_throw_sql_exception() ->
+ my_mysqli_real_connect()
+ my_mysqli_connect()
+
+ can't be tested: mysqli_query() via mysql_use_result()/mysql_store_result()
+ */
+ mysqli_report(MYSQLI_REPORT_OFF);
+ mysqli_report(MYSQLI_REPORT_STRICT);
+
+ try {
+
+ if ($link = my_mysqli_connect($host, $user . 'unknown_really', $passwd . 'non_empty', $db, $port, $socket))
+ printf("[012] Can connect to the server using host=%s, user=%s, passwd=***non_empty, dbname=%s, port=%s, socket=%s\n",
+ $host, $user . 'unknown_really', $db, $port, $socket);
+ mysqli_close($link);
+
+ } catch (mysqli_sql_exception $e) {
+ printf("[013] %s\n", $e->getMessage());
+ }
+
+ try {
+ if (!$link = mysqli_init())
+ printf("[014] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+ if ($link = my_mysqli_real_connect($link, $host, $user . 'unknown_really', $passwd . 'non_empty', $db, $port, $socket))
+ printf("[015] Can connect to the server using host=%s, user=%s, passwd=***non_empty, dbname=%s, port=%s, socket=%s\n",
+ $host, $user . 'unknown_really', $db, $port, $socket);
+ mysqli_close($link);
+ } catch (mysqli_sql_exception $e) {
+ printf("[016] %s\n", $e->getMessage());
+ }
+
+ /*
+ MYSQLI_REPORT_INDEX --->
+ mysqli_query()
+ mysqli_stmt_execute()
+ mysqli_prepare()
+ mysqli_real_query()
+ mysqli_store_result()
+ mysqli_use_result()
+
+ No test, because of to many prerequisites:
+ - Server needs to be started with and
+ --log-slow-queries --log-queries-not-using-indexes
+ - query must cause the warning on all MySQL versions
+
+ TODO:
+ */
+ $log_slow_queries = false;
+ $log_queries_not_using_indexes = false;
+ mysqli_report(MYSQLI_REPORT_OFF);
+ mysqli_report(MYSQLI_REPORT_INDEX);
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[017] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+ if (mysqli_get_server_version($link) <= 50600) {
+ // this might cause a warning - no index used
+ if (!$res = @mysqli_query($link, "SHOW VARIABLES LIKE 'log_slow_queries'"))
+ printf("[018] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$row = mysqli_fetch_assoc($res))
+ printf("[019] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $log_slow_query = ('ON' == $row['Value']);
+
+ if (mysqli_get_server_version($link) >= 50111) {
+ // this might cause a warning - no index used
+ if (!$res = @mysqli_query($link, "SHOW VARIABLES LIKE 'log_queries_not_using_indexes'"))
+ printf("[020] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$row = mysqli_fetch_assoc($res))
+ printf("[021] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $log_queries_not_using_indexes = ('ON' == $row['Value']);
+
+ if ($log_slow_queries && $log_queries_not_using_indexes) {
+
+ for ($i = 100; $i < 20000; $i++) {
+ if (!mysqli_query($link, "INSERT INTO test(id, label) VALUES ($i, 'z')"))
+ printf("[022 - %d] [%d] %s\n", $i - 99, mysqli_errno($link), mysqli_error($link));
+ }
+
+ // this might cause a warning - no index used
+ if (!$res = @mysqli_query($link, "SELECT id, label FROM test WHERE id = 1323"))
+ printf("[023] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ mysqli_free_result($res);
+ }
+ }
+ }
+
+ // Maybe we've provoked an index message, maybe not.
+ // All we can do is make a few dummy calls to ensure that all codes gets executed which
+ // checks the flag. Functions to check: mysqli_query() - done above,
+ // mysqli_stmt_execute(), mysqli_prepare(), mysqli_real_query(), mysqli_store_result()
+ // mysqli_use_result(), mysqli_thread_safe(), mysqli_thread_id()
+ mysqli_report(MYSQLI_REPORT_OFF);
+ mysqli_close($link);
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[024] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[025] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_stmt_prepare($stmt, 'SELECT id, label FROM test'))
+ printf("[026] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_execute($stmt))
+ printf("[027] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ mysqli_stmt_close($stmt);
+
+ if (!mysqli_real_query($link, 'SELECT label, id FROM test'))
+ printf("[028] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$res = mysqli_use_result($link))
+ printf("[029] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ mysqli_free_result($res);
+
+ if (!mysqli_real_query($link, 'SELECT label, id FROM test'))
+ printf("[030] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$res = mysqli_store_result($link))
+ printf("[031] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ mysqli_free_result($res);
+
+ if (!$stmt = mysqli_prepare($link, 'SELECT id * 3 FROM test'))
+ printf("[032] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ else
+ mysqli_stmt_close($stmt);
+
+ if (!mysqli_query($link, "INSERT INTO test(id, label) VALUES (100, 'z')", MYSQLI_USE_RESULT) ||
+ !mysqli_query($link, 'DELETE FROM test WHERE id > 50', MYSQLI_USE_RESULT))
+ printf("[033] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $tmp = mysqli_thread_safe($link);
+ $tmp = mysqli_thread_id($link);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Warning: mysqli_multi_query(): (%d/%d): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'BAR; FOO' at line 1 in %s on line %d
+
+Warning: mysqli_query(): (%d/%d): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'FOO' at line 1 in %s on line %d
+
+Warning: mysqli_change_user(): (%d/%d): Access denied for user '%s'@'%s' (using password: %s) in %s on line %d
+
+Warning: mysqli_kill(): processid should have positive value in %s on line %d
+
+Warning: mysqli_prepare(): (%d/%d): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'FOO' at line 1 in %s on line %d
+
+Warning: mysqli_real_query(): (%d/%d): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'FOO' at line 1 in %s on line %d
+
+Warning: mysqli_kill(): processid should have positive value in %s on line %d
+
+Warning: mysqli_stmt_prepare(): (%d/%d): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'FOO' at line 1 in %s on line %d
+[013] Access denied for user '%s'@'%s' (using password: YES)
+[016] Access denied for user '%s'@'%s' (using password: YES)
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_report_wo_ps.phpt b/ext/mysqli/tests/mysqli_report_wo_ps.phpt
new file mode 100644
index 0000000..cc57511
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_report_wo_ps.phpt
@@ -0,0 +1,113 @@
+--TEST--
+mysqli_report()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (NULL !== ($tmp = @mysqli_report()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (true !== ($tmp = mysqli_report(-1)))
+ printf("[002] Expecting boolean/true even for invalid flags, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (true !== ($tmp = mysqli_report(MYSQLI_REPORT_ERROR)))
+ printf("[003] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (true !== ($tmp = mysqli_report(MYSQLI_REPORT_STRICT)))
+ printf("[004] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (true !== ($tmp = mysqli_report(MYSQLI_REPORT_INDEX)))
+ printf("[005] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (true !== ($tmp = mysqli_report(MYSQLI_REPORT_ALL)))
+ printf("[007] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (true !== ($tmp = mysqli_report(MYSQLI_REPORT_OFF)))
+ printf("[008] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ /*
+ Internal macro MYSQL_REPORT_ERROR
+ */
+ mysqli_report(MYSQLI_REPORT_ERROR);
+
+ mysqli_multi_query($link, "BAR; FOO;");
+ mysqli_query($link, "FOO");
+ mysqli_change_user($link, "0123456789-10-456789-20-456789-30-456789-40-456789-50-456789-60-456789-70-456789-80-456789-90-456789", "password", $db);
+ mysqli_kill($link, -1);
+
+ // mysqli_ping() cannot be tested, because one would need to cause an error inside the C function to test it
+ mysqli_real_query($link, "FOO");
+ if (@mysqli_select_db($link, "Oh lord, let this be an unknown database name"))
+ printf("[009] select_db should have failed\n");
+ // mysqli_store_result() and mysqli_use_result() cannot be tested, because one would need to cause an error inside the C function to test it
+
+
+ // Check that none of the above would have caused any error messages if MYSQL_REPORT_ERROR would
+ // not have been set. If that would be the case, the test would be broken.
+ mysqli_report(MYSQLI_REPORT_OFF);
+
+ mysqli_multi_query($link, "BAR; FOO;");
+ mysqli_query($link, "FOO");
+ mysqli_change_user($link, "This might work if you accept anonymous users in your setup", "password", $db);
+ mysqli_kill($link, -1);
+ mysqli_real_query($link, "FOO");
+ mysqli_select_db($link, "Oh lord, let this be an unknown database name");
+
+ mysqli_report(MYSQLI_REPORT_OFF);
+ mysqli_report(MYSQLI_REPORT_STRICT);
+
+ try {
+
+ if ($link = my_mysqli_connect($host, $user . 'unknown_really', $passwd . 'non_empty', $db, $port, $socket))
+ printf("[010] Can connect to the server using host=%s, user=%s, passwd=***non_empty, dbname=%s, port=%s, socket=%s\n",
+ $host, $user . 'unknown_really', $db, $port, $socket);
+ mysqli_close($link);
+
+ } catch (mysqli_sql_exception $e) {
+ printf("[011] %s\n", $e->getMessage());
+ }
+
+ try {
+ if (!$link = mysqli_init())
+ printf("[012] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+ if ($link = my_mysqli_real_connect($link, $host, $user . 'unknown_really', $passwd . 'non_empty', $db, $port, $socket))
+ printf("[013] Can connect to the server using host=%s, user=%s, passwd=***non_empty, dbname=%s, port=%s, socket=%s\n",
+ $host, $user . 'unknown_really', $db, $port, $socket);
+ mysqli_close($link);
+ } catch (mysqli_sql_exception $e) {
+ printf("[014] %s\n", $e->getMessage());
+ }
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Warning: mysqli_multi_query(): (%d/%d): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'BAR; FOO' at line 1 in %s on line %d
+
+Warning: mysqli_query(): (%d/%d): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'FOO' at line 1 in %s on line %d
+
+Warning: mysqli_change_user(): (%d/%d): Access denied for user '%s'@'%s' (using password: %s) in %s on line %d
+
+Warning: mysqli_kill(): processid should have positive value in %s on line %d
+
+Warning: mysqli_real_query(): (%d/%d): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'FOO' at line 1 in %s on line %d
+
+Warning: mysqli_kill(): processid should have positive value in %s on line %d
+[011] Access denied for user '%s'@'%s' (using password: YES)
+[014] Access denied for user '%s'@'%s' (using password: YES)
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_result_references.phpt b/ext/mysqli/tests/mysqli_result_references.phpt
new file mode 100644
index 0000000..b6bce0d
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_result_references.phpt
@@ -0,0 +1,154 @@
+--TEST--
+References to result sets
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once('connect.inc');
+ require_once('table.inc');
+
+ $references = array();
+
+ if (!(mysqli_real_query($link, "SELECT id, label FROM test ORDER BY id ASC LIMIT 2")) ||
+ !($res = mysqli_store_result($link)))
+ printf("[001] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $idx = 0;
+ while ($row = mysqli_fetch_assoc($res)) {
+ /* mysqlnd: force seperation - create copies */
+ $references[$idx] = array(
+ 'id' => &$row['id'],
+ 'label' => $row['label'] . '');
+ $references[$idx++]['id'] += 0;
+ }
+
+ mysqli_close($link);
+
+ mysqli_data_seek($res, 0);
+ while ($row = mysqli_fetch_assoc($res)) {
+ /* mysqlnd: force seperation - create copies */
+ $references[$idx] = array(
+ 'id' => &$row['id'],
+ 'label' => $row['label'] . '');
+ $references[$idx++]['id'] += 0;
+ }
+
+ mysqli_free_result($res);
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[002] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ if (!(mysqli_real_query($link, "SELECT id, label FROM test ORDER BY id ASC LIMIT 2")) ||
+ !($res = mysqli_use_result($link)))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ while ($row = mysqli_fetch_assoc($res)) {
+ /* mysqlnd: force seperation - create copies*/
+ $references[$idx] = array(
+ 'id' => &$row['id'],
+ 'label' => $row['label'] . '');
+ $references[$idx]['id2'] = &$references[$idx]['id'];
+ $references[$idx]['id'] += 1;
+ $references[$idx++]['id2'] += 1;
+ }
+
+ $references[$idx++] = &$res;
+ mysqli_free_result($res);
+ @debug_zval_dump($references);
+
+ if (!(mysqli_real_query($link, "SELECT id, label FROM test ORDER BY id ASC LIMIT 1")) ||
+ !($res = mysqli_use_result($link)))
+ printf("[004] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $tmp = array();
+ while ($row = mysqli_fetch_assoc($res)) {
+ $tmp[] = $row;
+ }
+ $tmp = unserialize(serialize($tmp));
+ debug_zval_dump($tmp);
+ mysqli_free_result($res);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+array(7) refcount(2){
+ [0]=>
+ array(2) refcount(1){
+ [%u|b%"id"]=>
+ long(1) refcount(1)
+ [%u|b%"label"]=>
+ %unicode|string%(1) "a" refcount(1)
+ }
+ [1]=>
+ array(2) refcount(1){
+ [%u|b%"id"]=>
+ long(2) refcount(1)
+ [%u|b%"label"]=>
+ %unicode|string%(1) "b" refcount(1)
+ }
+ [2]=>
+ array(2) refcount(1){
+ [%u|b%"id"]=>
+ long(1) refcount(1)
+ [%u|b%"label"]=>
+ %unicode|string%(1) "a" refcount(1)
+ }
+ [3]=>
+ array(2) refcount(1){
+ [%u|b%"id"]=>
+ long(2) refcount(1)
+ [%u|b%"label"]=>
+ %unicode|string%(1) "b" refcount(1)
+ }
+ [4]=>
+ array(3) refcount(1){
+ [%u|b%"id"]=>
+ &long(3) refcount(2)
+ [%u|b%"label"]=>
+ %unicode|string%(1) "a" refcount(1)
+ [%u|b%"id2"]=>
+ &long(3) refcount(2)
+ }
+ [5]=>
+ array(3) refcount(1){
+ [%u|b%"id"]=>
+ &long(4) refcount(2)
+ [%u|b%"label"]=>
+ %unicode|string%(1) "b" refcount(1)
+ [%u|b%"id2"]=>
+ &long(4) refcount(2)
+ }
+ [6]=>
+ &object(mysqli_result)#2 (5) refcount(2){
+ [%u|b%"current_field"]=>
+ NULL refcount(1)
+ [%u|b%"field_count"]=>
+ NULL refcount(1)
+ [%u|b%"lengths"]=>
+ NULL refcount(1)
+ [%u|b%"num_rows"]=>
+ NULL refcount(1)
+ [%u|b%"type"]=>
+ NULL refcount(1)
+ }
+}
+array(1) refcount(2){
+ [0]=>
+ array(2) refcount(1){
+ [%u|b%"id"]=>
+ %unicode|string%(1) "1" refcount(1)
+ [%u|b%"label"]=>
+ %unicode|string%(1) "a" refcount(1)
+ }
+}
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_result_references_mysqlnd.phpt b/ext/mysqli/tests/mysqli_result_references_mysqlnd.phpt
new file mode 100644
index 0000000..384f85f
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_result_references_mysqlnd.phpt
@@ -0,0 +1,119 @@
+--TEST--
+References to result sets - mysqlnd (no copies but references)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+require_once('connect.inc');
+if (!$IS_MYSQLND)
+ die("skip Test for mysqlnd only");
+
+if ((version_compare(PHP_VERSION, '5.9.9', '>') == 1))
+ die("skip (TODO) PHP 6.0 has a difference debug_zval_dump output format");
+?>
+<?php require_once('skipifemb.inc'); ?>
+--FILE--
+<?php
+ require_once('connect.inc');
+ require_once('table.inc');
+
+ $references = array();
+
+ if (!(mysqli_real_query($link, "SELECT id, label FROM test ORDER BY id ASC LIMIT 1")) ||
+ !($res = mysqli_store_result($link)))
+ printf("[001] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $idx = 0;
+ while ($row = mysqli_fetch_assoc($res)) {
+ /* will overwrite itself */
+ $references[$idx]['row_ref'] = &$row;
+ $references[$idx]['row_copy'] = $row;
+ $references[$idx]['id_ref'] = &$row['id'];
+ $references[$idx++]['id_copy'] = $row['id'];
+ }
+
+ debug_zval_dump($references);
+ mysqli_free_result($res);
+
+ if (!(mysqli_real_query($link, "SELECT id, label FROM test ORDER BY id ASC LIMIT 2")) ||
+ !($res = mysqli_use_result($link)))
+ printf("[002] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $rows = array();
+ for ($i = 0; $i < 2; $i++) {
+ $rows[$i] = mysqli_fetch_assoc($res);
+ $references[$idx]['row_ref'] = &$rows[$i];
+ $references[$idx]['row_copy'] = $rows[$i];
+ $references[$idx]['id_ref'] = &$rows[$i]['id'];
+ $references[$idx]['id_copy'] = $rows[$i]['id'];
+ /* enforce seperation */
+ $references[$idx]['id_copy_mod']= $rows[$i]['id'] + 0;
+ }
+ mysqli_free_result($res);
+
+ debug_zval_dump($references);
+ print "done!";
+?>
+--EXPECTF--
+array(1) refcount(2){
+ [0]=>
+ array(4) refcount(1){
+ [%u|b%"row_ref"]=>
+ &NULL refcount(2)
+ [%u|b%"row_copy"]=>
+ array(2) refcount(1){
+ [%u|b%"id"]=>
+ %unicode|string%(1) "1" refcount(2)
+ [%u|b%"label"]=>
+ %unicode|string%(1) "a" refcount(2)
+ }
+ [%u|b%"id_ref"]=>
+ %unicode|string%(1) "1" refcount(1)
+ [%u|b%"id_copy"]=>
+ %unicode|string%(1) "1" refcount(1)
+ }
+}
+array(2) refcount(2){
+ [0]=>
+ array(4) refcount(1){
+ [%u|b%"row_ref"]=>
+ &NULL refcount(2)
+ [%u|b%"row_copy"]=>
+ array(2) refcount(1){
+ [%u|b%"id"]=>
+ %unicode|string%(1) "1" refcount(1)
+ [%u|b%"label"]=>
+ %unicode|string%(1) "a" refcount(1)
+ }
+ [%u|b%"id_ref"]=>
+ %unicode|string%(1) "1" refcount(1)
+ [%u|b%"id_copy"]=>
+ %unicode|string%(1) "1" refcount(1)
+ }
+ [1]=>
+ array(5) refcount(1){
+ [%u|b%"row_ref"]=>
+ &array(2) refcount(2){
+ [%u|b%"id"]=>
+ &%unicode|string%(1) "2" refcount(2)
+ [%u|b%"label"]=>
+ %unicode|string%(1) "b" refcount(2)
+ }
+ [%u|b%"row_copy"]=>
+ array(2) refcount(1){
+ [%u|b%"id"]=>
+ %unicode|string%(1) "2" refcount(1)
+ [%u|b%"label"]=>
+ %unicode|string%(1) "b" refcount(2)
+ }
+ [%u|b%"id_ref"]=>
+ &%unicode|string%(1) "2" refcount(2)
+ [%u|b%"id_copy"]=>
+ %unicode|string%(1) "2" refcount(1)
+ [%u|b%"id_copy_mod"]=>
+ long(2) refcount(1)
+ }
+}
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_result_unclonable.phpt b/ext/mysqli/tests/mysqli_result_unclonable.phpt
new file mode 100644
index 0000000..0ecc30b
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_result_unclonable.phpt
@@ -0,0 +1,24 @@
+--TEST--
+Trying to clone mysqli_result object
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[001] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ if (!($res = mysqli_query($link, "SELECT 'good' AS morning")))
+ printf("[002] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $res_clone = clone $res;
+ print "done!";
+?>
+--EXPECTF--
+Fatal error: Trying to clone an uncloneable object of class mysqli_result in %s on line %d \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_rollback.phpt b/ext/mysqli/tests/mysqli_rollback.phpt
new file mode 100644
index 0000000..be49000
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_rollback.phpt
@@ -0,0 +1,77 @@
+--TEST--
+mysqli_rollback()
+--SKIPIF--
+<?php ?>
+<?php ?>
+<?PHP
+ require_once('skipif.inc');
+ require_once('skipifemb.inc');
+ require_once('skipifconnectfailure.inc');
+
+ require_once('connect.inc');
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ die(sprintf("Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error()));
+
+ if (!have_innodb($link))
+ die(sprintf("Needs InnoDB support, [%d] %s", $link->errno, $link->error));
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_rollback()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_rollback($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[003] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ if (!is_null($tmp = @mysqli_rollback($link, 'foo')))
+ printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (true !== ($tmp = mysqli_autocommit($link, false)))
+ printf("[005] Cannot turn off autocommit, expecting true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_query($link, 'DROP TABLE IF EXISTS test'))
+ printf("[006] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, 'CREATE TABLE test(id INT) ENGINE = InnoDB'))
+ printf("[007] Cannot create test table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, 'INSERT INTO test(id) VALUES (1)'))
+ printf("[008] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $tmp = mysqli_rollback($link);
+ if ($tmp !== true)
+ printf("[009] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$res = mysqli_query($link, 'SELECT COUNT(*) AS num FROM test'))
+ printf("[011] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ $tmp = mysqli_fetch_assoc($res);
+ if (0 != $tmp['num'])
+ printf("[12] Expecting 0 rows in table test, found %d rows\n", $tmp['num']);
+ mysqli_free_result($res);
+
+ if (!mysqli_query($link, 'DROP TABLE IF EXISTS test'))
+ printf("[013] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ mysqli_close($link);
+
+ if (!is_null($tmp = mysqli_rollback($link)))
+ printf("[014] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!\n";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Warning: mysqli_rollback(): Couldn't fetch mysqli in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_select_db.phpt b/ext/mysqli/tests/mysqli_select_db.phpt
new file mode 100644
index 0000000..f58a19b
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_select_db.phpt
@@ -0,0 +1,112 @@
+--TEST--
+mysqli_select_db()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+ require_once("table.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_select_db()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_select_db($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[003] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ if (!is_null($tmp = @mysqli_select_db($link, $db, "foo")))
+ printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ /* does not make too much sense, unless we have access to at least one more database than $db */
+ if (!mysqli_select_db($link, $db))
+ printf("[005] Cannot select DB %s, [%d] %s\n", $db, mysqli_errno($link), mysqli_error($link));
+
+ if (!$res = mysqli_query($link, "SELECT DATABASE() AS dbname"))
+ printf("[006] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$row = mysqli_fetch_assoc($res))
+ printf("[007] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if ($row['dbname'] !== (string)$db)
+ printf("[008] Expecting database '%s', found '%s'\n", $db, $row['dbname']);
+ mysqli_free_result($res);
+
+ if (mysqli_select_db($link, 'mysql')) {
+ // Yippie, a second database to play with - that's great because mysqli_select_db
+ // ($db) was done by mysqli__connect() already and the previous test
+ // was quite useless
+ if (!$res = mysqli_query($link, "SELECT DATABASE() AS dbname"))
+ printf("[009] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$row = mysqli_fetch_assoc($res))
+ printf("[010] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (strtolower($row['dbname']) !== 'mysql')
+ printf("[011] Expecting database 'mysql', found '%s'\n", $row['dbname']);
+ mysqli_free_result($res);
+ }
+
+ if (!$link->select_db($db))
+ printf("[012] Failed to set '%s' as current DB; [%d] %s\n", $link->errno, $link->error);
+
+ if (!$res = mysqli_query($link, "SELECT DATABASE() AS dbname"))
+ printf("[013] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$row = mysqli_fetch_assoc($res))
+ printf("[014] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $current_db = $row['dbname'];
+
+ mysqli_report(MYSQLI_REPORT_OFF);
+ mysqli_select_db($link, 'I can not imagine that this database exists');
+ mysqli_report(MYSQLI_REPORT_ERROR);
+
+ ob_start();
+ mysqli_select_db($link, 'I can not imagine that this database exists');
+ $output = ob_get_contents();
+ ob_end_clean();
+ if (!stristr($output, "1049") && !stristr($output, "1044") && !stristr($output, "1045")) {
+ /* Error: 1049 SQLSTATE: 42000 (ER_BAD_DB_ERROR) Message: Unknown database '%s' */
+ /* Error: 1044 SQLSTATE: 42000 (ER_DBACCESS_DENIED_ERROR) Message: Access denied for user '%s'@'%s' to database '%s' */
+ /* Error: 1045 SQLSTATE: 28000 (ER_ACCESS_DENIED_ERROR) Message: Access denied for user '%s'@'%s' (using password: %s) */
+ echo $output;
+ }
+
+ if (!$res = mysqli_query($link, "SELECT DATABASE() AS dbname"))
+ printf("[015] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$row = mysqli_fetch_assoc($res))
+ printf("[016] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (strtolower($row['dbname']) != strtolower($current_db))
+ printf("[017] Current DB should not change if set fails\n");
+
+
+ if (!$res = $link->query("SELECT id FROM test WHERE id = 1"))
+ printf("[018] [%d] %s\n");
+
+ $row = $res->fetch_assoc();
+ $res->free();
+
+ mysqli_close($link);
+
+ if (NULL !== ($tmp = mysqli_select_db($link, $db)))
+ printf("[017] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!\n";
+?>
+--CLEAN--
+<?php require_once("clean_table.inc"); ?>
+--EXPECTF--
+Warning: mysqli_select_db(): Couldn't fetch mysqli in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_send_query.phpt b/ext/mysqli/tests/mysqli_send_query.phpt
new file mode 100644
index 0000000..7de2bfc
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_send_query.phpt
@@ -0,0 +1,50 @@
+--TEST--
+mysqli_send_query()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+if (!function_exists('mysqli_send_query')) {
+ die("skip mysqli_send_query() not available");
+}
+require_once('connect.inc');
+if (!$TEST_EXPERIMENTAL)
+ die("skip - experimental (= unsupported) feature");
+?>
+--FILE--
+<?php
+ /* NOTE: tests is a stub, but function is deprecated, as long as it does not crash when invoking it... */
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (NULL !== ($tmp = @mysqli_send_query()))
+ printf("[001] Expecting NULL/NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (NULL !== ($tmp = @mysqli_send_query($link)))
+ printf("[002] Expecting NULL/NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ printf("[003] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+ }
+
+ $query = array();
+ if (NULL !== ($tmp = @mysqli_send_query($link, $query)))
+ printf("[004] Expecting NULL/NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_int($tmp = mysqli_send_query($link, 'SELECT 1')))
+ printf("[005] Expecting integer/any value, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_close($link);
+
+ if (NULL !== ($tmp = mysqli_send_query($link, 'SELECT 1')))
+ printf("[006] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--EXPECTF--
+Warning: mysqli_send_query(): Couldn't fetch mysqli in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_set_charset.phpt b/ext/mysqli/tests/mysqli_set_charset.phpt
new file mode 100644
index 0000000..38fe568
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_set_charset.phpt
@@ -0,0 +1,134 @@
+--TEST--
+mysqli_set_charset()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+if (version_compare(PHP_VERSION, '5.9.9', '>') == 1) {
+ die('skip set character set not functional with PHP 6 (fomerly PHP 6 && unicode.semantics=On)');
+}
+
+if (!function_exists('mysqli_set_charset'))
+ die("skip Function not available");
+
+require_once('connect.inc');
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ die(sprintf("skip Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error()));
+
+if (!($res = mysqli_query($link, 'SELECT version() AS server_version')) ||
+ !($tmp = mysqli_fetch_assoc($res))) {
+ mysqli_close($link);
+ die(sprintf("skip Cannot check server version, [%d] %s\n",
+ mysqli_errno($link), mysqli_error($link)));
+}
+mysqli_free_result($res);
+$version = explode('.', $tmp['server_version']);
+if (empty($version)) {
+ mysqli_close($link);
+ die(sprintf("skip Cannot check server version, based on '%s'",
+ $tmp['server_version']));
+}
+
+if ($version[0] <= 4 && $version[1] < 1) {
+ mysqli_close($link);
+ die(sprintf("skip Requires MySQL Server 4.1+\n"));
+}
+
+if ((($res = mysqli_query($link, 'SHOW CHARACTER SET LIKE "latin1"', MYSQLI_STORE_RESULT)) &&
+ (mysqli_num_rows($res) == 1)) ||
+ (($res = mysqli_query($link, 'SHOW CHARACTER SET LIKE "latin2"', MYSQLI_STORE_RESULT)) &&
+ (mysqli_num_rows($res) == 1))
+ ) {
+ // ok, required latin1 or latin2 are available
+ mysqli_close($link);
+} else {
+ die(sprintf("skip Requires character set latin1 or latin2\n"));
+ mysqli_close($link);
+}
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_set_charset()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_set_charset($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_set_charset($link, $link)))
+ printf("[003] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (!$res = mysqli_query($link, 'SELECT @@character_set_connection AS charset, @@collation_connection AS collation'))
+ printf("[007] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ $tmp = mysqli_fetch_assoc($res);
+ mysqli_free_result($res);
+ if (!$character_set_connection = $tmp['charset'])
+ printf("[008] Cannot determine current character set and collation\n");
+
+ $new_charset = ('latin1' == $character_set_connection) ? 'latin2' : 'latin1';
+ if (!$res = mysqli_query($link, sprintf('SHOW CHARACTER SET LIKE "%s"', $new_charset), MYSQLI_STORE_RESULT))
+ printf("[009] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (mysqli_num_rows($res) == 0)
+ printf("[010] Test will fail, because alternative test character set '%s' seems not supported\n", $new_charset);
+
+ if (false !== ($ret = mysqli_set_charset($link, "this is not a valid character set")))
+ printf("[011] Expecting boolean/false because of invalid character set, got %s/%s\n", gettype($ret), $ret);
+
+ mysqli_close($link);
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[012] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ if (true !== ($ret = mysqli_set_charset($link, $new_charset)))
+ printf("[013] Expecting boolean/true, got %s/%s\n", gettype($ret), $ret);
+
+ if (!$res = mysqli_query($link, 'SELECT @@character_set_connection AS charset, @@collation_connection AS collation'))
+ printf("[014] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ $tmp = mysqli_fetch_assoc($res);
+ mysqli_free_result($res);
+ if ($new_charset !== $tmp['charset'])
+ printf("[015] Character set not changed? Expecting %s, got %s\n", $new_charset, $tmp['charset']);
+
+ if (!$res = mysqli_query($link, "SHOW CHARACTER SET"))
+ printf("[016] Cannot get list of character sets\n");
+
+ while ($tmp = mysqli_fetch_assoc($res)) {
+ if ('ucs2' == $tmp['Charset'] || 'utf16' == $tmp['Charset'] || 'utf32' == $tmp['Charset'] || 'utf16le' == $tmp['Charset'])
+ continue;
+
+ /* Uncomment to see where it hangs - var_dump($tmp); flush(); */
+ if (!@mysqli_set_charset($link, $tmp['Charset'])) {
+ printf("[017] Cannot set character set to '%s', [%d] %s\n", $tmp['Charset'],
+ mysqli_errno($link), mysqli_error($link));
+ continue;
+ }
+
+ /* Uncomment to see where it hangs - var_dump($tmp); flush(); */
+ if (!mysqli_query($link, sprintf("SET NAMES %s", mysqli_real_escape_string($link, $tmp['Charset']))))
+ printf("[018] Cannot run SET NAMES %s, [%d] %s\n", $tmp['Charset'], mysqli_errno($link), mysqli_error($link));
+ }
+ mysqli_free_result($res);
+
+ mysqli_close($link);
+
+ if (NULL !== ($tmp = mysqli_set_charset($link, $new_charset)))
+ printf("[016] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Warning: mysqli_set_charset(): Couldn't fetch mysqli in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_set_local_infile_default.phpt b/ext/mysqli/tests/mysqli_set_local_infile_default.phpt
new file mode 100644
index 0000000..0348b01
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_set_local_infile_default.phpt
@@ -0,0 +1,132 @@
+--TEST--
+mysqli_set_local_infile_default()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+if (!function_exists('mysqli_set_local_infile_handler'))
+ die("skip - function not available.");
+
+$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+if (!$link)
+ die(sprintf("skip Can't connect [%d] %s", mysqli_connect_errno(), mysqli_connect_error()));
+
+include_once("local_infile_tools.inc");
+if ($msg = check_local_infile_support($link, $engine))
+ die(sprintf("skip %s, [%d] %s", $msg, $link->errno, $link->error));
+
+mysqli_close($link);
+?>
+--INI--
+mysqli.allow_local_infile=1
+--FILE--
+<?php
+ require_once('connect.inc');
+ require_once('local_infile_tools.inc');
+
+ $link = $tmp = null;
+ if (!is_null($tmp = @mysqli_set_local_infile_default()))
+ printf("[001] Expecting NULL got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_set_local_infile_default($link)))
+ printf("[002] Expecting NULL got %s/%s\n", gettype($tmp), $tmp);
+
+ $link = new mysqli();
+ if (!is_null($tmp = @mysqli_set_local_infile_default($link)))
+ printf("[002a] Expecting NULL got %s/%s\n", gettype($tmp), $tmp);
+
+ include("table.inc");
+
+ if (!is_null($tmp = @mysqli_set_local_infile_default($link, 'foo')))
+ printf("[003] Expecting NULL got %s/%s\n", gettype($tmp), $tmp);
+
+
+ function callback_simple($fp, &$buffer, $buflen, &$error) {
+ static $invocation = 0;
+
+ printf("Callback: %d\n", $invocation);
+
+ $invocation++;
+ if (!is_resource($fp))
+ printf("[012] First argument passed to callback is not a resource but %s/%s\n",
+ $fp, gettype($fp));
+
+ if (!$buffer = fread($fp, $buflen)) {
+ if ($invocation == 1) {
+ printf("[013] Cannot read from stream\n");
+ $error = 'Cannot read from stream';
+ } else {
+ return strlen($buffer);
+ }
+ }
+
+ $lines = explode("\n", $buffer);
+ if (count($lines) != 4 && strlen($buffer) > 0) {
+ printf("[014] Test is too simple to handle a buffer of size %d that cannot hold all lines\n", $buflen);
+ $error = 'Parser too simple';
+ }
+
+ $buffer = '';
+ foreach ($lines as $k => $line) {
+ if ('' === trim($line))
+ continue;
+
+ $columns = explode(';', $line);
+ if (empty($columns)) {
+ printf("[015] Cannot parse columns\n");
+ $error = 'Cannot parse columns';
+ }
+
+ // increase id column value
+ $columns[0] += 1;
+ $buffer .= implode(';', $columns);
+ $buffer .= "\n";
+ }
+
+ return strlen($buffer);
+ }
+
+ $file = create_standard_csv(4);
+ $expected = array(
+ array('id' => 98, 'label' => 'x'),
+ array('id' => 99, 'label' => 'y'),
+ array('id' => 100, 'label' => 'z'),
+ );
+ try_handler(10, $link, $file, 'callback_simple', $expected);
+
+ $expected = array(
+ array('id' => 97, 'label' => 'x'),
+ array('id' => 98, 'label' => 'y'),
+ array('id' => 99, 'label' => 'z'),
+ );
+ try_handler(20, $link, $file, 'default', $expected);
+
+ $expected = array(
+ array('id' => 98, 'label' => 'x'),
+ array('id' => 99, 'label' => 'y'),
+ array('id' => 100, 'label' => 'z'),
+ );
+ try_handler(30, $link, $file, 'callback_simple', $expected);
+
+ mysqli_close($link);
+
+ if (!is_null($tmp = @mysqli_set_local_infile_default($link)))
+ printf("[300] Expecting NULL/NULL got %s/%s\n", $tmp, gettype($tmp));
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Callback set to 'callback_simple'
+Callback: 0
+Callback: 1
+Callback set to 'default'
+Callback set to 'callback_simple'
+Callback: 2
+Callback: 3
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_set_local_infile_handler.phpt b/ext/mysqli/tests/mysqli_set_local_infile_handler.phpt
new file mode 100644
index 0000000..58f4c70
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_set_local_infile_handler.phpt
@@ -0,0 +1,196 @@
+--TEST--
+mysqli_set_local_infile_handler()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+if (!function_exists('mysqli_set_local_infile_handler'))
+ die("skip - function not available.");
+
+require_once('connect.inc');
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ die("skip Cannot connect to MySQL");
+
+include_once("local_infile_tools.inc");
+if ($msg = check_local_infile_support($link, $engine))
+ die(sprintf("skip %s, [%d] %s", $msg, $link->errno, $link->error));
+
+mysqli_close($link);
+?>
+--INI--
+mysqli.allow_local_infile=1
+--FILE--
+<?php
+ require_once('connect.inc');
+ require_once('local_infile_tools.inc');
+ require_once('table.inc');
+
+ function callback_simple($fp, &$buffer, $buflen, &$error) {
+ static $invocation = 0;
+
+ printf("Callback: %d\n", $invocation);
+
+ $invocation++;
+ if (!is_resource($fp))
+ printf("[012] First argument passed to callback is not a resource but %s/%s\n",
+ $fp, gettype($fp));
+
+ if (!$buffer = fread($fp, $buflen)) {
+ if ($invocation == 1) {
+ printf("[013] Cannot read from stream\n");
+ $error = 'Cannot read from stream';
+ } else {
+ return strlen($buffer);
+ }
+ }
+
+ $lines = explode("\n", $buffer);
+ if (count($lines) != 4 && strlen($buffer) > 0) {
+ printf("[014] Test is too simple to handle a buffer of size %d that cannot hold all lines\n", $buflen);
+ $error = 'Parser too simple';
+ }
+
+ $buffer = '';
+ foreach ($lines as $k => $line) {
+ if ('' === trim($line))
+ continue;
+
+ $columns = explode(';', $line);
+ if (empty($columns)) {
+ printf("[015] Cannot parse columns\n");
+ $error = 'Cannot parse columns';
+ }
+
+ // increase id column value
+ $columns[0] += 1;
+ $buffer .= implode(';', $columns);
+ $buffer .= "\n";
+ }
+
+ return strlen($buffer);
+ }
+
+ function callback_fclose($fp, &$buffer, $buflen, &$error) {
+ static $invocation = 0;
+
+ printf("Callback: %d\n", $invocation++);
+
+ fclose($fp);
+ return strlen($buffer);
+ }
+
+ function callback_closefile($fp, &$buffer, $buflen, &$error) {
+ static $invocation = 0;
+
+ printf("Callback: %d\n", $invocation++);
+ flush();
+ if (is_resource($fp))
+ fclose($fp);
+ $buffer = "1;'a';\n";
+ if ($invocation > 10)
+ return 0;
+
+ return strlen($buffer);
+ }
+
+ function callback_invalid_args($fp, &$buffer, $buflen) {
+ static $invocation = 0;
+
+ printf("Callback: %d\n", $invocation++);
+ $buffer = fread($fp, $buflen);
+
+ return strlen($buffer);
+ }
+
+ function callback_error($fp, &$buffer, $buflen, &$error) {
+ static $invocation = 0;
+
+ printf("Callback: %d\n", $invocation++);
+ $buffer = fread($fp, $buflen);
+ $error = 'How to access this error?';
+
+ return -1;
+ }
+
+ if (!is_null($tmp = @mysqli_set_local_infile_handler()))
+ printf("[001] Expecting NULL/NULL got %s/%s\n", $tmp, gettype($tmp));
+
+ $handle = null;
+ if (!is_null($tmp = @mysqli_set_local_infile_handler($handle)))
+ printf("[002] Expecting NULL/NULL got %s/%s\n", $tmp, gettype($tmp));
+
+ $handle = @new mysqli();
+ if (!is_null($tmp = @mysqli_set_local_infile_handler($handle, 'callback_simple')))
+ printf("[003] Expecting NULL/NULL got %s/%s\n", $tmp, gettype($tmp));
+
+ if (false !== ($tmp = @mysqli_set_local_infile_handler($link, 'unknown')))
+ printf("[004] Expecting false/boolean got %s/%s\n", $tmp, gettype($tmp));
+
+ $file = create_standard_csv(5);
+
+ $expected = array(
+ array('id' => 98, 'label' => 'x'),
+ array('id' => 99, 'label' => 'y'),
+ array('id' => 100, 'label' => 'z'),
+ );
+ try_handler(10, $link, $file, 'callback_simple', $expected);
+
+ $expected = array();
+ try_handler(20, $link, $file, 'callback_fclose', $expected);
+
+ // FIXME - TODO - KLUDGE -
+ // IMHO this is wrong. ext/mysqli should bail as the function signature
+ // is not complete. That's a BC break, OK, but it makes perfectly sense.
+ $expected = array();
+ try_handler(30, $link, $file, 'callback_invalid_args', $expected);
+
+ $expected = array();
+ try_handler(40, $link, $file, 'callback_error', $expected);
+
+
+ mysqli_close($link);
+
+ if (!is_null($tmp = @mysqli_set_local_infile_handler($link, 'callback_simple')))
+ printf("[300] Expecting NULL/NULL got %s/%s\n", $tmp, gettype($tmp));
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Callback set to 'callback_simple'
+Callback: 0
+Callback: 1
+Callback set to 'callback_fclose'
+Callback: 0
+[022] LOAD DATA failed, [2000] File handle close%s
+Callback set to 'callback_invalid_args'
+Callback: 0
+Callback: 1
+[037] More results than expected!
+array(2) {
+ [%u|b%"id"]=>
+ %unicode|string%(2) "97"
+ [%u|b%"label"]=>
+ %unicode|string%(1) "x"
+}
+array(2) {
+ [%u|b%"id"]=>
+ %unicode|string%(2) "98"
+ [%u|b%"label"]=>
+ %unicode|string%(1) "y"
+}
+array(2) {
+ [%u|b%"id"]=>
+ %unicode|string%(2) "99"
+ [%u|b%"label"]=>
+ %unicode|string%(1) "z"
+}
+Callback set to 'callback_error'
+Callback: 0
+[042] LOAD DATA failed, [2000] How to access this error?
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_set_local_infile_handler_bad_character.phpt b/ext/mysqli/tests/mysqli_set_local_infile_handler_bad_character.phpt
new file mode 100644
index 0000000..b8f51c2
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_set_local_infile_handler_bad_character.phpt
@@ -0,0 +1,82 @@
+--TEST--
+mysqli_set_local_infile_handler() - random ASCII character including \0
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+require_once('connect.inc');
+
+if (!function_exists('mysqli_set_local_infile_handler'))
+ die("skip - function not available.");
+
+if (!$TEST_EXPERIMENTAL)
+ die("skip - experimental (= unsupported) feature");
+
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ die("skip Cannot connect to MySQL");
+
+include_once("local_infile_tools.inc");
+if ($msg = check_local_infile_support($link, $engine))
+ die(sprintf("skip %s, [%d] %s", $msg, $link->errno, $link->error));
+
+mysqli_close($link);
+?>
+--INI--
+mysqli.allow_local_infile=1
+--FILE--
+<?php
+ require_once('connect.inc');
+ require_once('local_infile_tools.inc');
+ require_once('table.inc');
+
+ function callback_bad_character($fp, &$buffer, $buflen, &$error) {
+ static $invocation = 0;
+
+ printf("Callback: %d\n", $invocation++);
+
+ $num_chars = (version_compare(PHP_VERSION, '5.9.9', '>') == 1) ? (floor($buflen / 2) - 10) : ($buflen - 5);
+ $part1 = floor($num_chars / 2);
+ $part2 = $num_chars - $part1;
+
+ $buffer = '';
+ for ($i = 0; $i < $part1; $i++)
+ $buffer .= chr(mt_rand(0, 255));
+
+ $buffer .= ';"';
+
+ for ($i = 0; $i < $part2; $i++)
+ $buffer .= chr(mt_rand(0, 255));
+
+ $buffer .= '";';
+ if ($invocation > 10)
+ return 0;
+
+ return strlen($buffer);
+ }
+
+ $file = create_standard_csv(5);
+ /* we feed the handler with random data, therefore we cannot specify and expected rows */
+ try_handler(20, $link, $file, 'callback_bad_character');
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Callback set to 'callback_bad_character'
+Callback: 0
+Callback: 1
+Callback: 2
+Callback: 3
+Callback: 4
+Callback: 5
+Callback: 6
+Callback: 7
+Callback: 8
+Callback: 9
+Callback: 10
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_set_local_infile_handler_buffer_overflow.phpt b/ext/mysqli/tests/mysqli_set_local_infile_handler_buffer_overflow.phpt
new file mode 100644
index 0000000..a3c8801
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_set_local_infile_handler_buffer_overflow.phpt
@@ -0,0 +1,60 @@
+--TEST--
+mysqli_set_local_infile_handler() - buffer overflow
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+if (!function_exists('mysqli_set_local_infile_handler'))
+ die("skip - function not available.");
+
+require_once('connect.inc');
+if (!$TEST_EXPERIMENTAL)
+ die("skip - experimental (= unsupported) feature");
+
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ die("skip Cannot connect to MySQL");
+
+include_once("local_infile_tools.inc");
+if ($msg = check_local_infile_support($link, $engine))
+ die(sprintf("skip %s, [%d] %s", $msg, $link->errno, $link->error));
+
+mysqli_close($link);
+?>
+--INI--
+mysqli.allow_local_infile=1
+--FILE--
+<?php
+ require_once('connect.inc');
+ require_once('local_infile_tools.inc');
+ require_once('table.inc');
+
+ function callback_buffer_overflow($fp, &$buffer, $buflen, &$error) {
+ static $invocation = 0;
+
+ printf("Callback: %d\n", $invocation);
+ $buffer = fread($fp, $buflen);
+
+ $buffer = str_repeat(';', $buflen * 2);
+ return strlen($buffer);
+ }
+
+ $file = create_standard_csv(5);
+ $expected = array();
+ try_handler(20, $link, $file, 'callback_buffer_overflow', $expected);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Callback set to 'callback_buffer_overflow'
+Callback: 0
+
+Warning: mysqli_query(): Too much data returned in %s on line %d
+[022] LOAD DATA failed, [%d] Too much data returned
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_set_local_infile_handler_close_link.phpt b/ext/mysqli/tests/mysqli_set_local_infile_handler_close_link.phpt
new file mode 100644
index 0000000..408bb29
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_set_local_infile_handler_close_link.phpt
@@ -0,0 +1,61 @@
+--TEST--
+mysqli_set_local_infile_handler() - close database link
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+if (!function_exists('mysqli_set_local_infile_handler'))
+ die("skip - function not available.");
+
+require_once('connect.inc');
+if (!$TEST_EXPERIMENTAL)
+ die("skip - experimental (= unsupported) feature");
+
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ die("skip Cannot connect to MySQL");
+
+include_once("local_infile_tools.inc");
+if ($msg = check_local_infile_support($link, $engine))
+ die(sprintf("skip %s, [%d] %s", $msg, $link->errno, $link->error));
+
+mysqli_close($link);
+?>
+--INI--
+mysqli.allow_local_infile=1
+--FILE--
+<?php
+ require("table.inc");
+ require_once('local_infile_tools.inc');
+
+ function callback_close_link($fp, &$buffer, $buflen, &$error) {
+ global $link;
+ static $invocation = 0;
+
+ printf("Callback: %d\n", $invocation++);
+ flush();
+ if (is_object($link))
+ mysqli_close($link);
+
+ $buffer = "1;'a';\n";
+ if ($invocation > 10)
+ return 0;
+
+ return strlen($buffer);
+ }
+
+ $file = create_standard_csv(1);
+ $expected = array(array('id' => 1, 'label' => 'a'));
+ try_handler(20, $link, $file, 'callback_close_link', $expected);
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Callback set to 'callback_close_link'
+Callback: 0
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_set_local_infile_handler_closefile.phpt b/ext/mysqli/tests/mysqli_set_local_infile_handler_closefile.phpt
new file mode 100644
index 0000000..168cbc1
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_set_local_infile_handler_closefile.phpt
@@ -0,0 +1,70 @@
+--TEST--
+mysqli_set_local_infile_handler() - do not use the file pointer
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+if (!function_exists('mysqli_set_local_infile_handler'))
+ die("skip - function not available.");
+
+require_once('connect.inc');
+if (!$TEST_EXPERIMENTAL)
+ die("skip - experimental (= unsupported) feature");
+
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ die("skip Cannot connect to MySQL");
+
+include_once("local_infile_tools.inc");
+if ($msg = check_local_infile_support($link, $engine))
+ die(sprintf("skip %s, [%d] %s", $msg, $link->errno, $link->error));
+
+mysqli_close($link);
+?>
+--INI--
+mysqli.allow_local_infile=1
+--FILE--
+<?php
+ require_once("table.inc");
+ require_once('local_infile_tools.inc');
+
+ function callback_closefile($fp, &$buffer, $buflen, &$error) {
+ static $invocation = 0;
+
+ printf("Callback: %d\n", $invocation++);
+ flush();
+ if (is_resource($fp))
+ fclose($fp);
+ $buffer = "1;'a';\n";
+ if ($invocation > 10)
+ return 0;
+
+ return strlen($buffer);
+ }
+
+ $file = create_standard_csv(1);
+ $expected = array(array('id' => 1, 'label' => 'a'));
+ try_handler(20, $link, $file, 'callback_closefile', $expected);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Callback set to 'callback_closefile'
+Callback: 0
+Callback: 1
+Callback: 2
+Callback: 3
+Callback: 4
+Callback: 5
+Callback: 6
+Callback: 7
+Callback: 8
+Callback: 9
+Callback: 10
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_set_local_infile_handler_closures.phpt b/ext/mysqli/tests/mysqli_set_local_infile_handler_closures.phpt
new file mode 100644
index 0000000..ad7ab32
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_set_local_infile_handler_closures.phpt
@@ -0,0 +1,62 @@
+--TEST--
+mysqli_set_local_infile_handler() - use closures as handler
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+if (!function_exists('mysqli_set_local_infile_handler'))
+ die("skip - function not available.");
+
+require_once('connect.inc');
+if (!$TEST_EXPERIMENTAL)
+ die("skip - experimental (= unsupported) feature");
+
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ die("skip Cannot connect to MySQL");
+
+include_once("local_infile_tools.inc");
+if ($msg = check_local_infile_support($link, $engine))
+ die(sprintf("skip %s, [%d] %s", $msg, $link->errno, $link->error));
+
+mysqli_close($link);
+?>
+--INI--
+mysqli.allow_local_infile=1
+--FILE--
+<?php
+ require_once('connect.inc');
+ require_once('local_infile_tools.inc');
+ require_once('table.inc');
+
+ $callback_replace_buffer = function ($fp, &$buffer, $buflen, &$error) {
+ static $invocation = 0;
+
+ printf("Callback: %d\n", $invocation++);
+ flush();
+
+ $buffer = fread($fp, $buflen);
+
+ if ($invocation > 10)
+ return 0;
+
+ return strlen($buffer);
+ };
+
+ $file = create_standard_csv(1);
+ if (!try_handler(20, $link, $file, $callback_replace_buffer, null))
+ printf("[008] Failure\n");
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Callback set to 'Closure object'
+Callback: 0
+Callback: 1
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_set_local_infile_handler_kill_link.phpt b/ext/mysqli/tests/mysqli_set_local_infile_handler_kill_link.phpt
new file mode 100644
index 0000000..b2b42a2
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_set_local_infile_handler_kill_link.phpt
@@ -0,0 +1,61 @@
+--TEST--
+mysqli_set_local_infile_handler() - kill database link
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+if (!function_exists('mysqli_set_local_infile_handler'))
+ die("skip - function not available.");
+
+require_once('connect.inc');
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ die("skip Cannot connect to MySQL");
+
+include_once("local_infile_tools.inc");
+if ($msg = check_local_infile_support($link, $engine))
+ die(sprintf("skip %s, [%d] %s", $msg, $link->errno, $link->error));
+
+mysqli_close($link);
+?>
+--INI--
+mysqli.allow_local_infile=1
+--FILE--
+<?php
+ require("table.inc");
+ require_once('local_infile_tools.inc');
+
+ function callback_kill_link($fp, &$buffer, $buflen, &$error) {
+ global $link;
+ static $invocation = 0;
+
+ printf("Callback: %d\n", $invocation++);
+ flush();
+ if (is_object($link))
+ mysqli_kill($link, mysqli_thread_id($link));
+
+ $buffer = "1;'a';\n";
+ if ($invocation > 10)
+ return 0;
+
+ mysqli_set_local_infile_default($link);
+ return strlen($buffer);
+ }
+
+ $file = create_standard_csv(1);
+ $expected = array(array('id' => 1, 'label' => 'a'));
+ try_handler(20, $link, $file, 'callback_kill_link', $expected);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Callback set to 'callback_kill_link'
+Callback: 0
+[022] LOAD DATA failed, [2000] Can't execute load data local init callback function
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_set_local_infile_handler_negative_len.phpt b/ext/mysqli/tests/mysqli_set_local_infile_handler_negative_len.phpt
new file mode 100644
index 0000000..16e38c5
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_set_local_infile_handler_negative_len.phpt
@@ -0,0 +1,58 @@
+--TEST--
+mysqli_set_local_infile_handler() - negative return value/buflen to indicate an error
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+if (!function_exists('mysqli_set_local_infile_handler'))
+ die("skip - function not available.");
+
+require_once('connect.inc');
+if (!$TEST_EXPERIMENTAL)
+ die("skip - experimental (= unsupported) feature");
+
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ die("skip Cannot connect to MySQL");
+
+include_once("local_infile_tools.inc");
+if ($msg = check_local_infile_support($link, $engine))
+ die(sprintf("skip %s, [%d] %s", $msg, $link->errno, $link->error));
+
+mysqli_close($link);
+?>
+--INI--
+mysqli.allow_local_infile=1
+--FILE--
+<?php
+ require_once('connect.inc');
+ require_once('local_infile_tools.inc');
+ require_once('table.inc');
+
+ function callback_negative_len($fp, &$buffer, $buflen, &$error) {
+ static $invocation = 0;
+
+ printf("Callback: %d\n", $invocation);
+ $buffer = fread($fp, $buflen);
+
+ $error = "negative length means error";
+ return -1;
+ }
+
+ $file = create_standard_csv(1);
+ $expected = array();
+ try_handler(20, $link, $file, 'callback_negative_len', $expected);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Callback set to 'callback_negative_len'
+Callback: 0
+[022] LOAD DATA failed, [2000] negative length means error
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_set_local_infile_handler_nested_call.phpt b/ext/mysqli/tests/mysqli_set_local_infile_handler_nested_call.phpt
new file mode 100644
index 0000000..4663fe2
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_set_local_infile_handler_nested_call.phpt
@@ -0,0 +1,107 @@
+--TEST--
+mysqli_set_local_infile_handler() - nested calls
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+if (!function_exists('mysqli_set_local_infile_handler'))
+ die("skip - function not available.");
+
+require_once('connect.inc');
+if (!$TEST_EXPERIMENTAL)
+ die("skip - experimental (= unsupported) feature");
+
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ die("skip Cannot connect to MySQL");
+
+include_once("local_infile_tools.inc");
+if ($msg = check_local_infile_support($link, $engine))
+ die(sprintf("skip %s, [%d] %s", $msg, $link->errno, $link->error));
+
+mysqli_close($link);
+?>
+--INI--
+mysqli.allow_local_infile=1
+--FILE--
+<?php
+ require_once('connect.inc');
+ require_once('local_infile_tools.inc');
+ require_once('table.inc');
+
+ function callback_simple($fp, &$buffer, $buflen, &$error) {
+ static $invocation = 0;
+
+ printf("Callback - callback_simple(): %d\n", $invocation);
+
+ $invocation++;
+ if (!is_resource($fp))
+ printf("[012] First argument passed to callback is not a resource but %s/%s\n",
+ $fp, gettype($fp));
+
+ if (!$buffer = fread($fp, $buflen)) {
+ if ($invocation == 1) {
+ printf("[013] Cannot read from stream\n");
+ $error = 'Cannot read from stream';
+ } else {
+ return strlen($buffer);
+ }
+ }
+
+ $lines = explode("\n", $buffer);
+ if (count($lines) != 4 && strlen($buffer) > 0) {
+ printf("[014] Test is too simple to handle a buffer of size %d that cannot hold all lines\n", $buflen);
+ $error = 'Parser too simple';
+ }
+
+ $buffer = '';
+ foreach ($lines as $k => $line) {
+ if ('' === trim($line))
+ continue;
+
+ $columns = explode(';', $line);
+ if (empty($columns)) {
+ printf("[015] Cannot parse columns\n");
+ $error = 'Cannot parse columns';
+ }
+
+ // increase id column value
+ $columns[0] += 1;
+ $buffer .= implode(';', $columns);
+ $buffer .= "\n";
+ }
+
+ /* report the wrong length */
+ return strlen($buffer);
+ }
+
+ function callback_report_short_len($fp, &$buffer, $buflen, &$error) {
+ static $invocation = 0;
+
+ printf("Callback - report_short_len(): %d\n", $invocation++);
+ return callback_simple($fp, $buffer, $buflen, $error);
+ }
+
+ $file = create_standard_csv(1);
+ $expected = array(
+ array('id' => 98, 'label' => 'x'),
+ array('id' => 99, 'label' => 'y'),
+ array('id' => 100, 'label' => 'z'),
+ );
+ try_handler(20, $link, $file, 'callback_report_short_len', $expected);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Callback set to 'callback_report_short_len'
+Callback - report_short_len(): 0
+Callback - callback_simple(): 0
+Callback - report_short_len(): 1
+Callback - callback_simple(): 1
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_set_local_infile_handler_new_query.phpt b/ext/mysqli/tests/mysqli_set_local_infile_handler_new_query.phpt
new file mode 100644
index 0000000..ca06435
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_set_local_infile_handler_new_query.phpt
@@ -0,0 +1,71 @@
+--TEST--
+mysqli_set_local_infile_handler() - run new query on db link
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+if (!function_exists('mysqli_set_local_infile_handler'))
+ die("skip - function not available.");
+
+require_once('connect.inc');
+if (!$TEST_EXPERIMENTAL)
+ die("skip - experimental (= unsupported) feature");
+
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ die("skip Cannot connect to MySQL");
+
+include_once("local_infile_tools.inc");
+if ($msg = check_local_infile_support($link, $engine))
+ die(sprintf("skip %s, [%d] %s", $msg, $link->errno, $link->error));
+
+mysqli_close($link);
+?>
+--INI--
+mysqli.allow_local_infile=1
+--FILE--
+<?php
+ require_once('connect.inc');
+ require_once('local_infile_tools.inc');
+ require_once('table.inc');
+
+ function callback_new_query($fp, &$buffer, $buflen, &$error) {
+ global $link;
+ static $invocation = 0;
+
+ printf("Callback: %d\n", $invocation++);
+ flush();
+ if (is_object($link)) {
+ if (!$res = mysqli_query($link, "SELECT id, label FROM test")) {
+ printf("[Callback 001 - %03d] Cannot run query, [%d] %s\n",
+ $invocation, mysqli_errno($link), mysqli_error($link));
+ }
+ if ($res)
+ mysqli_free_result($res);
+ }
+ $buffer = "1;'a';\n";
+ if ($invocation > 10)
+ return 0;
+
+ mysqli_set_local_infile_default($link);
+ return strlen($buffer);
+ }
+
+ $file = create_standard_csv(1);
+ $expected = array(array('id' => 1, 'label' => 'a'));
+ try_handler(20, $link, $file, 'callback_new_query', $expected);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Callback set to 'callback_new_query'
+Callback: 0
+[Callback 001 - 001] Cannot run query, [2014] Commands out of sync; you can't run this command now
+[022] LOAD DATA failed, [2000] Can't execute load data local init callback function
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_set_local_infile_handler_nofileop.phpt b/ext/mysqli/tests/mysqli_set_local_infile_handler_nofileop.phpt
new file mode 100644
index 0000000..601a09e
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_set_local_infile_handler_nofileop.phpt
@@ -0,0 +1,70 @@
+--TEST--
+mysqli_set_local_infile_handler() - do not use the file pointer
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+if (!function_exists('mysqli_set_local_infile_handler'))
+ die("skip - function not available.");
+
+require_once('connect.inc');
+if (!$TEST_EXPERIMENTAL)
+ die("skip - experimental (= unsupported) feature");
+
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ die("skip Cannot connect to MySQL");
+
+include_once("local_infile_tools.inc");
+if ($msg = check_local_infile_support($link, $engine))
+ die(sprintf("skip %s, [%d] %s", $msg, $link->errno, $link->error));
+
+mysqli_close($link);
+?>
+--INI--
+mysqli.allow_local_infile=1
+--FILE--
+<?php
+ require_once('connect.inc');
+ require_once('local_infile_tools.inc');
+ require_once('table.inc');
+
+ function callback_nofileop($fp, &$buffer, $buflen, &$error) {
+ static $invocation = 0;
+
+ printf("Callback: %d\n", $invocation++);
+ flush();
+
+ $buffer = "1;'a';\n";
+ if ($invocation > 10)
+ return 0;
+
+ return strlen($buffer);
+ }
+
+ $file = create_standard_csv(1);
+ $expected = array(array('id' => 1, 'label' => 'a'));
+ try_handler(20, $link, $file, 'callback_nofileop', $expected);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Callback set to 'callback_nofileop'
+Callback: 0
+Callback: 1
+Callback: 2
+Callback: 3
+Callback: 4
+Callback: 5
+Callback: 6
+Callback: 7
+Callback: 8
+Callback: 9
+Callback: 10
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_set_local_infile_handler_openbasedir.phpt b/ext/mysqli/tests/mysqli_set_local_infile_handler_openbasedir.phpt
new file mode 100644
index 0000000..7163aca
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_set_local_infile_handler_openbasedir.phpt
@@ -0,0 +1,115 @@
+--TEST--
+mysqli_set_local_infile_handler() - open basedir restrictions
+--SKIPIF--
+<?php
+if (!$fp = @fopen('skipif.inc', 'r'))
+ die("skip open_basedir restrictions forbid opening include files");
+
+include_once('skipif.inc');
+include_once('skipifemb.inc');
+include_once('skipifconnectfailure.inc');
+
+if (!function_exists('mysqli_set_local_infile_handler'))
+ die("skip - function not available.");
+
+include_once('connect.inc');
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ die("skip Cannot connect to MySQL");
+
+if (!$res = mysqli_query($link, 'SHOW VARIABLES LIKE "local_infile"')) {
+ mysqli_close($link);
+ die("skip Cannot check if Server variable 'local_infile' is set to 'ON'");
+}
+
+include_once("local_infile_tools.inc");
+if ($msg = check_local_infile_support($link, $engine))
+ die(sprintf("skip %s, [%d] %s", $msg, $link->errno, $link->error));
+
+mysqli_close($link);
+?>
+--INI--
+open_basedir="."
+--FILE--
+<?php
+ @include('connect.inc');
+ if (!isset($db)) {
+ // stupid run-tests.php - any idea how to set system ini setting dynamically???
+ print "Warning: tempnam(): open_basedir restriction in effect. File(grrr) is not within the allowed path(s): (grrr) in grrr on line 0
+[005 + 1] Cannot create CVS file ''
+Callback set to 'callback_simple'
+[012] LOAD DATA failed, [0] grrr
+[014/0] [0] ''
+done!";
+ die();
+ }
+
+ require_once('connect.inc');
+ require_once('local_infile_tools.inc');
+ require_once('table.inc');
+
+ function callback_simple($fp, &$buffer, $buflen, &$error) {
+ static $invocation = 0;
+
+ printf("Callback: %d\n", $invocation);
+
+ $invocation++;
+ if (!is_resource($fp))
+ printf("[012] First argument passed to callback is not a resource but %s/%s\n",
+ $fp, gettype($fp));
+
+ if (!$buffer = fread($fp, $buflen)) {
+ if ($invocation == 1) {
+ printf("[013] Cannot read from stream\n");
+ $error = 'Cannot read from stream';
+ } else {
+ return strlen($buffer);
+ }
+ }
+
+ $lines = explode("\n", $buffer);
+ if (count($lines) != 4 && strlen($buffer) > 0) {
+ printf("[014] Test is too simple to handle a buffer of size %d that cannot hold all lines\n", $buflen);
+ $error = 'Parser too simple';
+ }
+
+ $buffer = '';
+ foreach ($lines as $k => $line) {
+ if ('' === trim($line))
+ continue;
+
+ $columns = explode(';', $line);
+ if (empty($columns)) {
+ printf("[015] Cannot parse columns\n");
+ $error = 'Cannot parse columns';
+ }
+
+ // increase id column value
+ $columns[0] += 1;
+ $buffer .= implode(';', $columns);
+ $buffer .= "\n";
+ }
+
+ return strlen($buffer);
+ }
+
+ $file = create_standard_csv(5);
+ $expected = array(
+ array('id' => 98, 'label' => 'x'),
+ array('id' => 99, 'label' => 'y'),
+ array('id' => 100, 'label' => 'z'),
+ );
+ try_handler(10, $link, $file, 'callback_simple', $expected);
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Warning: tempnam(): open_basedir restriction in effect. File(%s) is not within the allowed path(s): (%s) in %s on line %d
+[005 + 1] Cannot create CVS file ''
+Callback set to 'callback_simple'
+[012] LOAD DATA failed, [%d] %s
+[014/0] [0] ''
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_set_local_infile_handler_replace_buffer.phpt b/ext/mysqli/tests/mysqli_set_local_infile_handler_replace_buffer.phpt
new file mode 100644
index 0000000..0d4024e
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_set_local_infile_handler_replace_buffer.phpt
@@ -0,0 +1,78 @@
+--TEST--
+mysqli_set_local_infile_handler() - replace buffer pointer
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+if (!function_exists('mysqli_set_local_infile_handler'))
+ die("skip - function not available.");
+
+require_once('connect.inc');
+if (!$TEST_EXPERIMENTAL)
+ die("skip - experimental (= unsupported) feature");
+
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ die("skip Cannot connect to MySQL");
+
+include_once("local_infile_tools.inc");
+if ($msg = check_local_infile_support($link, $engine))
+ die(sprintf("skip %s, [%d] %s", $msg, $link->errno, $link->error));
+
+mysqli_close($link);
+?>
+--INI--
+mysqli.allow_local_infile=1
+--FILE--
+<?php
+ require_once('connect.inc');
+ require_once('local_infile_tools.inc');
+ require_once('table.inc');
+
+ function callback_replace_buffer($fp, &$buffer, $buflen, &$error) {
+ static $invocation = 0;
+
+ printf("Callback: %d\n", $invocation++);
+ flush();
+
+ $buffer = fread($fp, $buflen);
+
+ $ret = "1;'a';\n";
+ $buffer = $ret;
+
+ $num_chars = ((version_compare(PHP_VERSION, '5.9.9', '>') == 1)) ? floor($buflen / 2) : $buflen;
+ assert(strlen($buffer) < $num_chars);
+
+ if ($invocation > 10)
+ return 0;
+
+ return strlen($buffer);
+ }
+
+ $file = create_standard_csv(1);
+ $expected = array(array('id' => 1, 'label' => 'a'));
+ if (!try_handler(20, $link, $file, 'callback_replace_buffer', $expected))
+ printf("[008] Failure\n");
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Callback set to 'callback_replace_buffer'
+Callback: 0
+Callback: 1
+Callback: 2
+Callback: 3
+Callback: 4
+Callback: 5
+Callback: 6
+Callback: 7
+Callback: 8
+Callback: 9
+Callback: 10
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_set_local_infile_handler_short_len.phpt b/ext/mysqli/tests/mysqli_set_local_infile_handler_short_len.phpt
new file mode 100644
index 0000000..b3144e4
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_set_local_infile_handler_short_len.phpt
@@ -0,0 +1,101 @@
+--TEST--
+mysqli_set_local_infile_handler() - report shorter buffer
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+if (!function_exists('mysqli_set_local_infile_handler'))
+ die("skip - function not available.");
+
+require_once('connect.inc');
+if (!$TEST_EXPERIMENTAL)
+ die("skip - experimental (= unsupported) feature");
+
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ die("skip Cannot connect to MySQL");
+
+include_once("local_infile_tools.inc");
+if ($msg = check_local_infile_support($link, $engine))
+ die(sprintf("skip %s, [%d] %s", $msg, $link->errno, $link->error));
+
+mysqli_close($link);
+?>
+--INI--
+mysqli.allow_local_infile=1
+--FILE--
+<?php
+ require_once('connect.inc');
+ require_once('local_infile_tools.inc');
+ require_once('table.inc');
+
+ function callback_short_len($fp, &$buffer, $buflen, &$error) {
+ static $invocation = 0;
+
+ printf("Callback: %d\n", $invocation);
+
+ $invocation++;
+ if (!is_resource($fp))
+ printf("[012] First argument passed to callback is not a resource but %s/%s\n",
+ $fp, gettype($fp));
+
+ if (!$buffer = fread($fp, $buflen)) {
+ if ($invocation == 1) {
+ printf("[013] Cannot read from stream\n");
+ $error = 'Cannot read from stream';
+ } else {
+ return strlen($buffer);
+ }
+ }
+
+ $lines = explode("\n", $buffer);
+ if (count($lines) != 4 && strlen($buffer) > 0) {
+ printf("[014] Test is too simple to handle a buffer of size %d that cannot hold all lines\n", $buflen);
+ $error = 'Parser too simple';
+ }
+
+ $buffer = '';
+ foreach ($lines as $k => $line) {
+ if ('' === trim($line))
+ continue;
+
+ $columns = explode(';', $line);
+ if (empty($columns)) {
+ printf("[015] Cannot parse columns\n");
+ $error = 'Cannot parse columns';
+ }
+
+ // increase id column value
+ $columns[0] += 1;
+ $buffer .= implode(';', $columns);
+ $buffer .= "\n";
+ }
+
+ /* report the wrong length */
+ return strlen($buffer) - 1;
+ }
+
+ $file = create_standard_csv(1);
+ $expected = array(
+ array('id' => 98, 'label' => 'x'),
+ array('id' => 99, 'label' => 'y'),
+ array('id' => 100, 'label' => 'z'),
+ );
+ try_handler(20, $link, $file, 'callback_short_len', $expected);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Callback set to 'callback_short_len'
+Callback: 0
+
+Warning: mysqli_query(): Mismatch between the return value of the callback and the content length of the buffer. in %s on line %d
+[022] LOAD DATA failed, [2000] Mismatch between the return value of the callback and the content length of the buffer.
+[024/0] [0] ''
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_set_local_infile_handler_unregister.phpt b/ext/mysqli/tests/mysqli_set_local_infile_handler_unregister.phpt
new file mode 100644
index 0000000..f287f4d
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_set_local_infile_handler_unregister.phpt
@@ -0,0 +1,64 @@
+--TEST--
+mysqli_set_local_infile_handler() - do not use the file pointer
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+if (!function_exists('mysqli_set_local_infile_handler'))
+ die("skip - function not available.");
+
+require_once('connect.inc');
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ die("skip Cannot connect to MySQL");
+
+include_once("local_infile_tools.inc");
+if ($msg = check_local_infile_support($link, $engine))
+ die(sprintf("skip %s, [%d] %s", $msg, $link->errno, $link->error));
+
+mysqli_close($link);
+?>
+--INI--
+mysqli.allow_local_infile=1
+--FILE--
+<?php
+ require_once('connect.inc');
+ require_once('local_infile_tools.inc');
+ require_once('table.inc');
+
+ function callback_unregister($fp, &$buffer, $buflen, &$error) {
+ global $link;
+ static $invocation = 0;
+
+ printf("Callback: %d\n", $invocation++);
+ flush();
+ if (is_resource($fp))
+ fclose($fp);
+ $buffer = "1;'a';\n";
+ if ($invocation > 10)
+ return 0;
+
+ mysqli_set_local_infile_default($link);
+ return strlen($buffer);
+ }
+
+ $file = create_standard_csv(1);
+ $expected = array(array('id' => 1, 'label' => 'a'));
+ try_handler(20, $link, $file, 'callback_unregister', $expected);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Callback set to 'callback_unregister'
+Callback: 0
+
+Warning: mysqli_query(): File handle closed in %s on line %d
+[022] LOAD DATA failed, [2000] File handle closed
+[024/0] [0] ''
+done!
diff --git a/ext/mysqli/tests/mysqli_set_opt.phpt b/ext/mysqli/tests/mysqli_set_opt.phpt
new file mode 100644
index 0000000..7c96d59
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_set_opt.phpt
@@ -0,0 +1,69 @@
+--TEST--
+mysqli_set_opt()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_set_opt()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_set_opt($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ $link = mysqli_init();
+
+ if (!is_null($tmp = @mysqli_set_opt($link, MYSQLI_OPT_CONNECT_TIMEOUT)))
+ printf("[003] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_set_opt($link, "s", 'extra_my.cnf')))
+ printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_set_opt($link, MYSQLI_INIT_COMMAND, 'SET AUTOCOMMIT=0', 'foo')))
+ printf("[005] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ // print "run_tests.php don't fool me with your 'ungreedy' expression '.+?'!\n";
+ var_dump(mysqli_set_opt($link, MYSQLI_READ_DEFAULT_GROUP, 'extra_my.cnf'));
+ var_dump(mysqli_set_opt($link, MYSQLI_READ_DEFAULT_FILE, 'extra_my.cnf'));
+ var_dump(mysqli_set_opt($link, MYSQLI_OPT_CONNECT_TIMEOUT, 10));
+ var_dump(mysqli_set_opt($link, MYSQLI_OPT_LOCAL_INFILE, 1));
+ var_dump(mysqli_set_opt($link, MYSQLI_INIT_COMMAND, 'SET AUTOCOMMIT=0'));
+ var_dump(my_mysqli_real_connect($link, $host, $user, $passwd, $db, $port, $socket));
+ var_dump(mysqli_set_opt($link, MYSQLI_READ_DEFAULT_GROUP, 'extra_my.cnf'));
+ var_dump(mysqli_set_opt($link, MYSQLI_READ_DEFAULT_FILE, 'extra_my.cnf'));
+ var_dump(mysqli_set_opt($link, MYSQLI_OPT_CONNECT_TIMEOUT, 10));
+ var_dump(mysqli_set_opt($link, MYSQLI_OPT_LOCAL_INFILE, 1));
+ var_dump(mysqli_set_opt($link, MYSQLI_INIT_COMMAND, 'SET AUTOCOMMIT=0'));
+ var_dump(mysqli_set_opt($link, MYSQLI_CLIENT_SSL, 'not an mysqli_option'));
+
+ mysqli_close($link);
+
+ var_dump(mysqli_set_opt($link, MYSQLI_INIT_COMMAND, 'SET AUTOCOMMIT=1'));
+
+ print "done!";
+?>
+--EXPECTF--
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(false)
+
+Warning: mysqli_set_opt(): Couldn't fetch mysqli in %s on line %d
+NULL
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_sqlstate.phpt b/ext/mysqli/tests/mysqli_sqlstate.phpt
new file mode 100644
index 0000000..56580cd
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_sqlstate.phpt
@@ -0,0 +1,50 @@
+--TEST--
+mysqli_sqlstate()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_sqlstate()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_sqlstate($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ var_dump(@mysqli_sqlstate($link, "foo"));
+
+ var_dump(mysqli_sqlstate($link));
+ mysqli_query($link, "SELECT unknown_column FROM test");
+ var_dump(mysqli_sqlstate($link));
+ mysqli_free_result(mysqli_query($link, "SELECT id FROM test"));
+ var_dump(mysqli_sqlstate($link));
+
+ mysqli_close($link);
+
+ var_dump(mysqli_sqlstate($link));
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+NULL
+%s(5) "00000"
+%s(5) "42S22"
+%s(5) "00000"
+
+Warning: mysqli_sqlstate(): Couldn't fetch mysqli in %s on line %d
+NULL
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_ssl_set.phpt b/ext/mysqli/tests/mysqli_ssl_set.phpt
new file mode 100644
index 0000000..2abae55
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_ssl_set.phpt
@@ -0,0 +1,61 @@
+--TEST--
+mysqli_ssl_set() - test is a stub!
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+if (!function_exists('mysqli_ssl_set'))
+ die("skip function not available");
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_ssl_set()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_ssl_set($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_ssl_set($link, $link)))
+ printf("[003] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_ssl_set($link, $link, $link)))
+ printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_ssl_set($link, $link, $link, $link)))
+ printf("[005] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_ssl_set($link, $link, $link, $link, $link)))
+ printf("[006] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ /*
+ This function always returns TRUE value.
+
+ $link = mysqli_init();
+ if (NULL !== ($tmp = @mysqli_ssl_set(
+ $link,
+ 'The path name to the key file.',
+ 'The path name to the certificate file.',
+ 'The path name to the certificate authority file.',
+ 'The pathname to a directory that contains trusted SSL CA certificates in PEM format.',
+ 'A list of allowable ciphers to use for SSL encryption.')))
+ printf("[007] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+
+ If SSL setup is incorrect my_mysqli_real_connect()
+ will return an error when you attempt to connect.
+
+ ... and the above SSL setup should be always incorrect.
+
+ if (false !== ($tmp = my_mysqli_real_connect($link, $host, $user, $passwd, $db, $port, $socket)))
+ printf("[008] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+ */
+ print "done!\n";
+?>
+--EXPECTF--
+done!
diff --git a/ext/mysqli/tests/mysqli_stat.phpt b/ext/mysqli/tests/mysqli_stat.phpt
new file mode 100644
index 0000000..f1cd56c
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stat.phpt
@@ -0,0 +1,40 @@
+--TEST--
+mysqli_stat()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_stat()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stat($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (!is_null($tmp = @mysqli_stat($link, "foo")))
+ printf("[003] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if ((!is_string($tmp = mysqli_stat($link))) || ('' === $tmp))
+ printf("[004] Expecting non empty string, got %s/'%s', [%d] %s\n",
+ gettype($tmp), $tmp, mysqli_errno($link), mysql_error($link));
+
+ mysqli_close($link);
+
+ if (!is_null($tmp = mysqli_stat($link)))
+ printf("[005] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--EXPECTF--
+Warning: mysqli_stat(): Couldn't fetch mysqli in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_affected_rows.phpt b/ext/mysqli/tests/mysqli_stmt_affected_rows.phpt
new file mode 100644
index 0000000..7fc32f7
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_affected_rows.phpt
@@ -0,0 +1,252 @@
+--TEST--
+mysqli_stmt_affected_rows()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_stmt_affected_rows()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_affected_rows($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ printf("Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+ }
+ $stmt = mysqli_stmt_init($link);
+
+ if (!mysqli_stmt_prepare($stmt, 'DROP TABLE IF EXISTS test') ||
+ !mysqli_stmt_execute($stmt)) {
+ printf("[003] Failed to drop old test table: [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ }
+
+ if (!mysqli_stmt_prepare($stmt, 'CREATE TABLE test(id INT, label CHAR(1), PRIMARY KEY(id)) ENGINE = ' . $engine) ||
+ !mysqli_stmt_execute($stmt)) {
+ printf("[004] Failed to create test table: [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ }
+
+ if (0 !== ($tmp = mysqli_stmt_affected_rows($stmt)))
+ printf("[005] Expecting int/0, got %s/'%s'\n", gettype($tmp), $tmp);
+
+ mysqli_stmt_close($stmt);
+ $stmt = mysqli_stmt_init($link);
+
+ if (!mysqli_stmt_prepare($stmt, "INSERT INTO test(id, label) VALUES (1, 'a')") ||
+ !mysqli_stmt_execute($stmt))
+ printf("[006] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ mysqli_stmt_close($stmt);
+ $stmt = mysqli_stmt_init($link);
+
+ if (!mysqli_stmt_prepare($stmt, "INSERT INTO test(id, label) VALUES (100, 'z')") ||
+ !mysqli_stmt_execute($stmt))
+ printf("[007] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (1 !== ($tmp = mysqli_stmt_affected_rows($stmt)))
+ printf("[008] Expecting int/1, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_stmt_close($stmt);
+ $stmt = mysqli_stmt_init($link);
+
+ if (!mysqli_stmt_prepare($stmt, "INSERT INTO test(id, label) VALUES (100, 'z')") ||
+ !mysqli_stmt_execute($stmt))
+ // NOTE: the error message varies with the MySQL Server version, dump only the error code!
+ printf("[009] [%d] (error message varies with the MySQL Server version, check the error code)\n", mysqli_stmt_errno($stmt));
+
+ /* an error occurred: affected rows should return -1 */
+ if (-1 !== ($tmp = mysqli_stmt_affected_rows($stmt)))
+ printf("[010] Expecting int/0, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_stmt_close($stmt);
+ $stmt = mysqli_stmt_init($link);
+
+ if (!mysqli_stmt_prepare($stmt, "INSERT INTO test(id, label) VALUES (1, 'a') ON DUPLICATE KEY UPDATE id = 4") ||
+ !mysqli_stmt_execute($stmt))
+ printf("[011] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (2 !== ($tmp = mysqli_stmt_affected_rows($stmt)))
+ printf("[012] Expecting int/2, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_stmt_close($stmt);
+ $stmt = mysqli_stmt_init($link);
+
+ if (!mysqli_stmt_prepare($stmt, "INSERT INTO test(id, label) VALUES (2, 'b'), (3, 'c')") ||
+ !mysqli_stmt_execute($stmt))
+ printf("[013] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (2 !== ($tmp = mysqli_stmt_affected_rows($stmt)))
+ printf("[014] Expecting int/2, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_stmt_close($stmt);
+ $stmt = mysqli_stmt_init($link);
+
+ if (!mysqli_stmt_prepare($stmt, "INSERT IGNORE INTO test(id, label) VALUES (1, 'a')") ||
+ !mysqli_stmt_execute($stmt))
+ printf("[015] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (1 !== ($tmp = mysqli_stmt_affected_rows($stmt)))
+ printf("[016] Expecting int/1, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!($res = mysqli_query($link, "SELECT count(id) AS num FROM test")) ||
+ !($tmp = mysqli_fetch_assoc($res)))
+ printf("[017] [%d] %s\n", mysqli_error($link), mysqli_error($link));
+ $num = (int)$tmp['num'];
+ mysqli_free_result($res);
+
+ mysqli_stmt_close($stmt);
+ $stmt = mysqli_stmt_init($link);
+
+ if (!mysqli_stmt_prepare($stmt, "INSERT INTO test(id, label) SELECT id + 10, label FROM test") ||
+ !mysqli_stmt_execute($stmt))
+ printf("[018] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if ($num !== ($tmp = mysqli_stmt_affected_rows($stmt)))
+ printf("[019] Expecting int/%d, got %s/%s\n", $num, gettype($tmp), $tmp);
+
+ mysqli_stmt_close($stmt);
+ $stmt = mysqli_stmt_init($link);
+
+ if (!mysqli_stmt_prepare($stmt, "REPLACE INTO test(id, label) values (4, 'd')") ||
+ !mysqli_stmt_execute($stmt))
+ printf("[020] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (2 !== ($tmp = mysqli_stmt_affected_rows($stmt)))
+ printf("[021] Expecting int/2, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_stmt_close($stmt);
+ $stmt = mysqli_stmt_init($link);
+
+ if (!mysqli_stmt_prepare($stmt, "REPLACE INTO test(id, label) values (5, 'e')") ||
+ !mysqli_stmt_execute($stmt))
+ printf("[022] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (1 !== ($tmp = mysqli_stmt_affected_rows($stmt)))
+ printf("[023] Expecting int/1, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_stmt_close($stmt);
+ $stmt = mysqli_stmt_init($link);
+
+ if (!mysqli_stmt_prepare($stmt, "UPDATE test SET label = 'a' WHERE id = 2") ||
+ !mysqli_stmt_execute($stmt))
+ printf("[024] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (1 !== ($tmp = mysqli_stmt_affected_rows($stmt)))
+ printf("[025] Expecting int/1, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_prepare($stmt, "UPDATE test SET label = 'a' WHERE id = 2") ||
+ !mysqli_stmt_execute($stmt))
+ printf("[026] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (0 !== ($tmp = mysqli_stmt_affected_rows($stmt)))
+ printf("[027] Expecting int/0, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_stmt_close($stmt);
+ $stmt = mysqli_stmt_init($link);
+
+ if (!mysqli_stmt_prepare($stmt, "UPDATE test SET label = 'a' WHERE id = 100") ||
+ !mysqli_stmt_execute($stmt))
+ printf("[028] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (1 !== ($tmp = mysqli_stmt_affected_rows($stmt)))
+ printf("[029] Expecting int/1, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_prepare($stmt, 'SELECT label FROM test WHERE id = 100') ||
+ !mysqli_stmt_execute($stmt))
+ printf("[030] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ /* use it like num_rows */
+ /* PS are unbuffered, num_rows cannot determine the row count before all rows have been fetched and/or buffered */
+ if (-1 !== ($tmp = mysqli_stmt_affected_rows($stmt)))
+ printf("[031] Expecting int/-1, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (0 !== ($tmp = mysqli_stmt_num_rows($stmt)))
+ printf("[032] Expecting int/0, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_store_result($stmt))
+ printf("[033] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (1 !== ($tmp = mysqli_stmt_affected_rows($stmt)))
+ printf("[034] Expecting int/0, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (1 !== ($tmp = mysqli_stmt_num_rows($stmt)))
+ printf("[035] Expecting int/0, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_stmt_free_result($stmt);
+ mysqli_stmt_close($stmt);
+ $stmt = mysqli_stmt_init($link);
+
+ if (!mysqli_stmt_prepare($stmt, 'SELECT label FROM test WHERE 1 = 2') ||
+ !mysqli_stmt_execute($stmt))
+ printf("[036] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ /* use it like num_rows */
+ if (-1 !== ($tmp = mysqli_stmt_affected_rows($stmt)))
+ printf("[037] Expecting int/-1, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (true !== ($tmp = mysqli_stmt_store_result($stmt)))
+ printf("[038] Expecting boolean/true, got %s\%s\n", gettype($tmp), $tmp);
+
+ if (0 !== ($tmp = mysqli_stmt_num_rows($stmt)))
+ printf("[039] Expecting int/0, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (0 !== ($tmp = mysqli_stmt_affected_rows($stmt)))
+ printf("[040] Expecting int/0, got %s/%s\n", gettype($tmp), $tmp);
+
+ /* try to use stmt_affected_rows like stmt_num_rows */
+ /* stmt_affected_rows is not really meant for SELECT! */
+ if (mysqli_stmt_prepare($stmt, 'SELECT unknown_column FROM this_table_does_not_exist') ||
+ mysqli_stmt_execute($stmt))
+ printf("[041] The invalid SELECT statement is issued on purpose\n");
+
+ if (-1 !== ($tmp = mysqli_stmt_affected_rows($stmt)))
+ printf("[042] Expecting int/-1, got %s/%s\n", gettype($tmp), $tmp);
+
+ if ($IS_MYSQLND) {
+ if (false !== ($tmp = mysqli_stmt_store_result($stmt)))
+ printf("[043] Expecting boolean/false, got %s\%s\n", gettype($tmp), $tmp);
+ } else {
+ if (true !== ($tmp = mysqli_stmt_store_result($stmt)))
+ printf("[043] Libmysql does not care if the previous statement was bogus, expecting boolean/true, got %s\%s\n", gettype($tmp), $tmp);
+ }
+
+ if (0 !== ($tmp = mysqli_stmt_num_rows($stmt)))
+ printf("[044] Expecting int/0, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (-1 !== ($tmp = mysqli_stmt_affected_rows($stmt)))
+ printf("[045] Expecting int/-1, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_stmt_close($stmt);
+ $stmt = mysqli_stmt_init($link);
+
+ if (!mysqli_stmt_prepare($stmt, "DROP TABLE IF EXISTS test") ||
+ !mysqli_stmt_execute($stmt))
+ printf("[046] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ mysqli_stmt_close($stmt);
+
+ if (!is_null($tmp = mysqli_stmt_affected_rows($stmt)))
+ printf("[047] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_close($link);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+[009] [%d] (error message varies with the MySQL Server version, check the error code)
+
+Warning: mysqli_stmt_affected_rows(): Couldn't fetch mysqli_stmt in %s on line %d
+done!
diff --git a/ext/mysqli/tests/mysqli_stmt_attr_get.phpt b/ext/mysqli/tests/mysqli_stmt_attr_get.phpt
new file mode 100644
index 0000000..a4eb4d0
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_attr_get.phpt
@@ -0,0 +1,70 @@
+--TEST--
+mysqli_stmt_attr_get()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_stmt_attr_get()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_attr_get($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_attr_get($link, $link)))
+ printf("[003] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (!is_null($tmp = @mysqli_stmt_attr_get($link, $link)))
+ printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ $valid_attr = array("max_length" => MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH);
+ if (mysqli_get_client_version() > 50003)
+ $valid_attr["cursor_type"] = MYSQLI_STMT_ATTR_CURSOR_TYPE;
+
+ if ($IS_MYSQLND && mysqli_get_client_version() > 50007)
+ $valid_attr["prefetch_rows"] = MYSQLI_STMT_ATTR_PREFETCH_ROWS;
+
+ do {
+ $invalid_attr = mt_rand(0, 10000);
+ } while (in_array($invalid_attr, $valid_attr));
+
+ $stmt = mysqli_stmt_init($link);
+ mysqli_stmt_prepare($stmt, 'SELECT * FROM test');
+ if (false !== ($tmp = @mysqli_stmt_attr_get($stmt, $invalid_attr)))
+ printf("[005] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ foreach ($valid_attr as $k => $attr) {
+ if (false === ($tmp = mysqli_stmt_attr_get($stmt, $attr))) {
+ printf("[006] Expecting any type, but not boolean/false, got %s/%s for attribute %s/%s\n",
+ gettype($tmp), $tmp, $k, $attr);
+ }
+ }
+
+ $stmt->close();
+
+ foreach ($valid_attr as $k => $attr) {
+ if (!is_null($tmp = @mysqli_stmt_attr_get($stmt, $attr))) {
+ printf("[007] Expecting NULL/NULL, got %s/%s for attribute %s/%s\n",
+ gettype($tmp), $tmp, $k, $attr);
+ }
+ }
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+done!
diff --git a/ext/mysqli/tests/mysqli_stmt_attr_get_prefetch.phpt b/ext/mysqli/tests/mysqli_stmt_attr_get_prefetch.phpt
new file mode 100644
index 0000000..0d5e8f9
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_attr_get_prefetch.phpt
@@ -0,0 +1,29 @@
+--TEST--
+mysqli_stmt_attr_get() - prefetch
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+die("SKIP: prefetch isn't supported at the moment");
+?>
+--FILE--
+<?php
+ require('table.inc');
+
+ $stmt = mysqli_stmt_init($link);
+ mysqli_stmt_prepare($stmt, 'SELECT * FROM test');
+ if (1 !== ($tmp = mysqli_stmt_attr_get($stmt, MYSQLI_STMT_ATTR_PREFETCH_ROWS))) {
+ printf("[001] Expecting int/1, got %s/%s for attribute %s/%s\n",
+ gettype($tmp), $tmp, $k, $attr);
+ }
+ $stmt->close();
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_attr_set.phpt b/ext/mysqli/tests/mysqli_stmt_attr_set.phpt
new file mode 100644
index 0000000..c2ddd21
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_attr_set.phpt
@@ -0,0 +1,277 @@
+--TEST--
+mysqli_stmt_attr_set() - mysqlnd does not check for invalid codes
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_stmt_attr_set()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_attr_set($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_attr_set($link, $link)))
+ printf("[003] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_attr_set($link, $link, $link)))
+ printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ $valid_attr = array(MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH);
+ if ((mysqli_get_client_version() > 50003) || $IS_MYSQLND) {
+ $valid_attr[] = MYSQLI_STMT_ATTR_CURSOR_TYPE;
+ $valid_attr[] = MYSQLI_CURSOR_TYPE_NO_CURSOR;
+ $valid_attr[] = MYSQLI_CURSOR_TYPE_READ_ONLY;
+ $valid_attr[] = MYSQLI_CURSOR_TYPE_FOR_UPDATE;
+ $valid_attr[] = MYSQLI_CURSOR_TYPE_SCROLLABLE;
+ }
+
+ if ((mysqli_get_client_version() > 50007) || $IS_MYSQLND)
+ $valid_attr[] = MYSQLI_STMT_ATTR_PREFETCH_ROWS;
+
+
+ $stmt = mysqli_stmt_init($link);
+ if (!is_null($tmp = @mysqli_stmt_attr_set($stmt, 0, 0)))
+ printf("[005] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ $stmt->prepare("SELECT * FROM test");
+
+ mt_srand(microtime(true));
+
+ for ($i = -100; $i < 1000; $i++) {
+ if (in_array($i, $valid_attr))
+ continue;
+ $invalid_attr = $i;
+ if (false !== ($tmp = @mysqli_stmt_attr_set($stmt, $invalid_attr, 0))) {
+ printf("[006a] Expecting boolean/false for attribute %d, got %s/%s\n", $invalid_attr, gettype($tmp), $tmp);
+ }
+ }
+
+ for ($i = 0; $i < 2; $i++) {
+ do {
+ $invalid_attr = mt_rand(-1 * (min(4294967296, PHP_INT_MAX) + 1), min(4294967296, PHP_INT_MAX));
+ } while (in_array($invalid_attr, $valid_attr));
+ if (false !== ($tmp = @mysqli_stmt_attr_set($stmt, $invalid_attr, 0))) {
+ printf("[006b] Expecting boolean/false for attribute %d, got %s/%s\n", $invalid_attr, gettype($tmp), $tmp);
+ }
+ }
+ $stmt->close();
+
+ //
+ // MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH
+ //
+
+
+ // expecting max_length not to be set and be 0 in all cases
+ $stmt = mysqli_stmt_init($link);
+ $stmt->prepare("SELECT label FROM test");
+ $stmt->execute();
+ $stmt->store_result();
+ $res = $stmt->result_metadata();
+ $fields = $res->fetch_fields();
+ $max_lengths = array();
+ foreach ($fields as $k => $meta) {
+ $max_lengths[$meta->name] = $meta->max_length;
+ if ($meta->max_length !== 0)
+ printf("[007] max_length should be not set (= 0), got %s for field %s\n", $meta->max_length, $meta->name);
+ }
+ $res->close();
+ $stmt->close();
+
+ // expecting max_length to _be_ set
+ $stmt = mysqli_stmt_init($link);
+ $stmt->prepare("SELECT label FROM test");
+ $stmt->attr_set(MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH, 1);
+ $res = $stmt->attr_get(MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH);
+ if ($res !== 1)
+ printf("[007.1] max_length should be 1, got %s\n", $res);
+ $stmt->execute();
+ $stmt->store_result();
+ $res = $stmt->result_metadata();
+ $fields = $res->fetch_fields();
+ $max_lengths = array();
+ foreach ($fields as $k => $meta) {
+ $max_lengths[$meta->name] = $meta->max_length;
+ if ($meta->max_length === 0)
+ printf("[008] max_length should be set (!= 0), got %s for field %s\n", $meta->max_length, $meta->name);
+ }
+ $res->close();
+ $stmt->close();
+
+ // expecting max_length not to be set
+ $stmt = mysqli_stmt_init($link);
+ $stmt->prepare("SELECT label FROM test");
+ $stmt->attr_set(MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH, 0);
+ $res = $stmt->attr_get(MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH);
+ if ($res !== 0)
+ printf("[008.1] max_length should be 0, got %s\n", $res);
+ $stmt->execute();
+ $stmt->store_result();
+ $res = $stmt->result_metadata();
+ $fields = $res->fetch_fields();
+ $max_lengths = array();
+ foreach ($fields as $k => $meta) {
+ $max_lengths[$meta->name] = $meta->max_length;
+ if ($meta->max_length !== 0)
+ printf("[009] max_length should not be set (= 0), got %s for field %s\n", $meta->max_length, $meta->name);
+ }
+ $res->close();
+ $stmt->close();
+
+ //
+ // Cursors
+ //
+
+ if (mysqli_get_client_version() > 50003) {
+
+ $cursor_types = array(
+ MYSQLI_CURSOR_TYPE_NO_CURSOR,
+ MYSQLI_CURSOR_TYPE_READ_ONLY,
+ MYSQLI_CURSOR_TYPE_FOR_UPDATE,
+ MYSQLI_CURSOR_TYPE_SCROLLABLE
+ );
+ do {
+ $invalid_cursor_type = mt_rand(-1000, 1000);
+ } while (in_array($invalid_cursor_type, $cursor_types));
+
+ $stmt = mysqli_stmt_init($link);
+ $stmt->prepare("SELECT id, label FROM test");
+
+ if (false !== ($tmp = @$stmt->attr_set(MYSQLI_STMT_ATTR_CURSOR_TYPE, $invalid_cursor_type)))
+ printf("[010] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (false !== ($tmp = $stmt->attr_set(MYSQLI_STMT_ATTR_CURSOR_TYPE, MYSQLI_CURSOR_TYPE_FOR_UPDATE)))
+ printf("[011] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (false !== ($tmp = $stmt->attr_set(MYSQLI_STMT_ATTR_CURSOR_TYPE, MYSQLI_CURSOR_TYPE_SCROLLABLE)))
+ printf("[012] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (true !== ($tmp = $stmt->attr_set(MYSQLI_STMT_ATTR_CURSOR_TYPE, MYSQLI_CURSOR_TYPE_NO_CURSOR)))
+ printf("[013] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (true !== ($tmp = $stmt->attr_set(MYSQLI_STMT_ATTR_CURSOR_TYPE, MYSQLI_CURSOR_TYPE_READ_ONLY)))
+ printf("[014] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ $stmt->close();
+
+ $stmt = mysqli_stmt_init($link);
+ $stmt->prepare("SELECT id, label FROM test");
+ $stmt->execute();
+ $id = $label = NULL;
+ $stmt->bind_result($id, $label);
+ $results = array();
+ while ($stmt->fetch())
+ $results[$id] = $label;
+ $stmt->close();
+ if (empty($results))
+ printf("[015] Results should not be empty, subsequent tests will probably fail!\n");
+
+ $stmt = mysqli_stmt_init($link);
+ $stmt->prepare("SELECT id, label FROM test");
+ if (true !== ($tmp = $stmt->attr_set(MYSQLI_STMT_ATTR_CURSOR_TYPE, MYSQLI_CURSOR_TYPE_NO_CURSOR)))
+ printf("[016] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+ $stmt->execute();
+ $id = $label = NULL;
+ $stmt->bind_result($id, $label);
+ $results2 = array();
+ while ($stmt->fetch())
+ $results2[$id] = $label;
+ $stmt->close();
+ if ($results != $results2) {
+ printf("[017] Results should not differ. Dumping both result sets.\n");
+ var_dump($results);
+ var_dump($results2);
+ }
+
+ $stmt = mysqli_stmt_init($link);
+ $stmt->prepare("SELECT id, label FROM test");
+ if (true !== ($tmp = $stmt->attr_set(MYSQLI_STMT_ATTR_CURSOR_TYPE, MYSQLI_CURSOR_TYPE_READ_ONLY)))
+ printf("[018] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+ $stmt->execute();
+ $id = $label = NULL;
+ $stmt->bind_result($id, $label);
+ $results2 = array();
+ while ($stmt->fetch())
+ $results2[$id] = $label;
+ $stmt->close();
+ if ($results != $results2) {
+ printf("[019] Results should not differ. Dumping both result sets.\n");
+ var_dump($results);
+ var_dump($results2);
+ }
+
+ }
+
+
+ //
+ // MYSQLI_STMT_ATTR_PREFETCH_ROWS
+ //
+
+ if (mysqli_get_client_version() > 50007) {
+
+ $stmt = mysqli_stmt_init($link);
+ $stmt->prepare("SELECT id, label FROM test");
+ if (true !== ($tmp = $stmt->attr_set(MYSQLI_STMT_ATTR_PREFETCH_ROWS, 1)))
+ printf("[020] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+ $stmt->execute();
+ $id = $label = NULL;
+ $stmt->bind_result($id, $label);
+ $results = array();
+ while ($stmt->fetch())
+ $results[$id] = $label;
+ $stmt->close();
+ if (empty($results))
+ printf("[021] Results should not be empty, subsequent tests will probably fail!\n");
+
+ /* prefetch is not supported
+ $stmt = mysqli_stmt_init($link);
+ $stmt->prepare("SELECT label FROM test");
+ if (false !== ($tmp = $stmt->attr_set(MYSQLI_STMT_ATTR_PREFETCH_ROWS, -1)))
+ printf("[022] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+ $stmt->close();
+
+ $stmt = mysqli_stmt_init($link);
+ $stmt->prepare("SELECT label FROM test");
+ if (true !== ($tmp = $stmt->attr_set(MYSQLI_STMT_ATTR_PREFETCH_ROWS, PHP_INT_MAX)))
+ printf("[023] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+ $stmt->close();
+
+ $stmt = mysqli_stmt_init($link);
+ $stmt->prepare("SELECT id, label FROM test");
+ if (true !== ($tmp = $stmt->attr_set(MYSQLI_STMT_ATTR_PREFETCH_ROWS, 2)))
+ printf("[024] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+ $stmt->execute();
+ $id = $label = NULL;
+ $stmt->bind_result($id, $label);
+ $results2 = array();
+ while ($stmt->fetch())
+ $results2[$id] = $label;
+ $stmt->close();
+ if ($results != $results2) {
+ printf("[025] Results should not differ. Dumping both result sets.\n");
+ var_dump($results);
+ var_dump($results2);
+ }
+ */
+
+ }
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+done!
diff --git a/ext/mysqli/tests/mysqli_stmt_bind_limits.phpt b/ext/mysqli/tests/mysqli_stmt_bind_limits.phpt
new file mode 100644
index 0000000..39c6020
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_bind_limits.phpt
@@ -0,0 +1,129 @@
+--TEST--
+Bind limits
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ function bind_many($offset, $link, $num_params, $rows, $eval = true) {
+
+ $drop = "DROP TABLE IF EXISTS test";
+ $create = "CREATE TABLE test(id INT AUTO_INCREMENT PRIMARY KEY, ";
+ $insert = "INSERT INTO test";
+ $columns = "";
+ $values = "";
+ $stmt_params = "";
+ $params = array();
+ for ($i = 0; $i < $num_params; $i++) {
+ $create .= "col" . $i . " INT, ";
+ $columns .= "col" . $i . ", ";
+ $values .= "?, ";
+ $stmt_params .= '$params[' . $i . '], ';
+ for ($j = 0; $j < $rows; $j++)
+ $params[($j * $rows) + $i] = $i;
+ }
+ $create = substr($create, 0, -2) . ")";
+
+ $stmt_types = str_repeat("i", $num_params * $rows);
+ $stmt_params = substr(str_repeat($stmt_params, $rows), 0, -2);
+ $values = substr($values, 0, -2);
+ $insert .= "(" . substr($columns, 0, -2) . ") VALUES ";
+ $insert .= substr(str_repeat("(" . $values . "), ", $rows), 0, -2);
+
+ $stmt_bind_param = 'return mysqli_stmt_bind_param($stmt, "' . $stmt_types . '", ' . $stmt_params . ');';
+
+ printf("Testing %d columns with %d rows...\n", $num_params, $rows);
+
+ if (!$link->query($drop) || !$link->query($create)) {
+ printf("[%03d + 01] [%d] %s\n", $offset, $link->errno, $link->error);
+ return false;
+ }
+ printf("... table created\n");
+
+ if (!$stmt = $link->prepare($insert)) {
+ printf("[%03d + 02] [%d] %s\n", $offset, $link->errno, $link->error);
+ return false;
+ }
+ if ($stmt->param_count != $num_params * $rows) {
+ printf("[%03d + 03] Parameter count should be %d but got %d\n", $offset, $num_params * $rows, $stmt->param_count);
+ return false;
+ }
+ printf("... statement with %d parameters prepared\n", $stmt->param_count);
+
+ if ($eval) {
+ if (!eval($stmt_bind_param)) {
+ printf("[%03d + 03] [%d] %s\n", $offset, $stmt->errno, $stmt->error);
+ return false;
+ }
+ } else {
+ $param_ref = array($stmt_types);
+ for ($i = 0; $i < $rows; $i++)
+ for ($j = 0; $j < $num_params; $j++)
+ $param_ref[] = &$params[($i * $rows) + $j];
+
+ if (!call_user_func_array(array($stmt, 'bind_param'), $param_ref)) {
+ printf("[%03d + 03] [%d] %s\n", $offset, $stmt->errno, $stmt->error);
+ return false;
+ }
+ }
+ if ($stmt->param_count != $num_params * $rows) {
+ printf("[%03d + 03] Parameter count should be %d but got %d\n", $offset, $num_params * $rows, $stmt->param_count);
+ return false;
+ }
+
+ if (!$stmt->execute()) {
+ printf("[%03d + 04] [%d] %s\n", $offset, $stmt->errno, $stmt->error);
+ return false;
+ }
+ printf("Statement done\n");
+
+ $stmt->close();
+
+ if (!($res = $link->query("SELECT * FROM test"))) {
+ printf("[%03d + 05] [%d] %s\n", $offset, $link->errno, $link->error);
+ return false;
+ }
+
+ $row = $res->fetch_row();
+ $res->close();
+
+ for ($i = 0; $i < $num_params; $i++) {
+ if ($row[$i + 1] != $i) {
+ printf("[%03d + 06] [%d] %s\n", $offset, $link->errno, $link->error);
+ }
+ }
+
+ return true;
+ }
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ printf("[001] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+ }
+
+ var_dump(bind_many(10, $link, 273, 240, true));
+ var_dump(bind_many(20, $link, 273, 240, false));
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+require_once("clean_table.inc");
+?>
+--EXPECTF--
+Testing 273 columns with 240 rows...
+... table created
+... statement with 65520 parameters prepared
+Statement done
+bool(true)
+Testing 273 columns with 240 rows...
+... table created
+... statement with 65520 parameters prepared
+Statement done
+bool(true)
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_bind_param.phpt b/ext/mysqli/tests/mysqli_stmt_bind_param.phpt
new file mode 100644
index 0000000..d2d8254
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_bind_param.phpt
@@ -0,0 +1,404 @@
+--TEST--
+mysqli_stmt_bind_param()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ /*
+ The way we test the INSERT and data types overlaps with
+ the mysqli_stmt_bind_result test in large parts. There is only
+ one difference. This test uses mysqli_query()/mysqli_fetch_assoc() to
+ fetch the inserted values. This way we test
+ mysqli_query()/mysqli_fetch_assoc() for all possible data types
+ in this file and we test mysqli_stmt_bind_result() in the other
+ test -- therefore the "duplicate" makes some sense to me.
+ */
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_stmt_bind_param()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_bind_param($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_bind_param($link, $link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ $stmt = mysqli_stmt_init($link);
+ if (!mysqli_stmt_prepare($stmt, "INSERT INTO test(id, label) VALUES (?, ?)"))
+ printf("[003] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = null;
+ $label = null;
+
+ /*
+ libmysql gives a less descriptive error message but mysqlnd,
+ we did not unify the error messages but ignore this slight difference silently
+ */
+ if (!false === ($tmp = @mysqli_stmt_bind_param($stmt, " ", $tmp)))
+ printf("[003d] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!false === ($tmp = @mysqli_stmt_bind_param($stmt, "", $id, $label)))
+ printf("[003a] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ /* TODO: somehwhat undocumented syntax! */
+ $param = array($id);
+ if (!false === ($tmp = mysqli_stmt_bind_param($stmt, "is", $param)))
+ printf("[003b] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ $param = array($id, $label, $id);
+ if (!false === ($tmp = mysqli_stmt_bind_param($stmt, "is", $param)))
+ printf("[003c] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!false === ($tmp = mysqli_stmt_bind_param($stmt, "a", $id)))
+ printf("[004] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!false === ($tmp = mysqli_stmt_bind_param($stmt, "a", $id, $label)))
+ printf("[005] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!false === ($tmp = mysqli_stmt_bind_param($stmt, "aa", $id, $label)))
+ printf("[006] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!false === ($tmp = mysqli_stmt_bind_param($stmt, "ia", $id, $label)))
+ printf("[007] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!true === ($tmp = mysqli_stmt_bind_param($stmt, "is", $id, $label)))
+ printf("[008] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (function_exists("memory_get_usage")) {
+ $mem = memory_get_usage();
+ for ($i = 0; $i < 20000; $i++) {
+ if (!true === ($tmp = mysqli_stmt_bind_param($stmt, "is", $id, $label)))
+ printf("[008][$i] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+ }
+ if (($tmp = (memory_get_usage() - $mem)) > 600)
+ printf("[009] Function seems to be leaking, because it used %d bytes. During tests it used only 92 bytes.", $tmp);
+ }
+
+ $id = 100;
+ $label = "z";
+ if (!mysqli_stmt_execute($stmt))
+ printf("[010] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ mysqli_stmt_close($stmt);
+
+ if (!($res = mysqli_query($link, "SELECT id, label FROM test WHERE id = " . $id)))
+ printf("[011] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ $row = mysqli_fetch_assoc($res);
+ if (($row['id'] != $id) || ($row['label'] != $label))
+ printf("[012] Expecting '%s'/%s', got '%s'/%s'!\n", $id, $label, $row['id'], $row['label']);
+ mysqli_free_result($res);
+
+ function func_mysqli_stmt_bind_datatype($link, $engine, $bind_type, $sql_type, $bind_value, $offset, $alternative = null) {
+
+ if (!mysqli_query($link, "DROP TABLE IF EXISTS test")) {
+ printf("[%03d] [%d] %s\n", $offset, mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ if (!mysqli_query($link, sprintf("CREATE TABLE test(id INT NOT NULL, label %s, PRIMARY KEY(id)) ENGINE = %s", $sql_type, $engine))) {
+ // don't bail - it might be that the server does not support the data type
+ return false;
+ }
+
+ if (!$stmt = mysqli_stmt_init($link)) {
+ printf("[%03d] [%d] %s\n", $offset + 1, mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ if (!mysqli_stmt_prepare($stmt, "INSERT INTO test(id, label) VALUE (?, ?)")) {
+ printf("[%03d] [%d] %s\n", $offset + 2, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ return false;
+ }
+
+ $id = 1;
+ if (!mysqli_stmt_bind_param($stmt, "i" . $bind_type, $id, $bind_value)) {
+ printf("[%03d] [%d] %s\n", $offset + 3, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ return false;
+ }
+
+ if (!mysqli_stmt_execute($stmt)) {
+ printf("[%03d] [%d] %s\n", $offset + 4, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ return false;
+ }
+ mysqli_stmt_close($stmt);
+
+ if (!$res = mysqli_query($link, "SELECT id, label FROM test")) {
+ printf("[%03d] [%d] %s\n", $offset + 5, mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ if (!$row = mysqli_fetch_assoc($res)) {
+ printf("[%03d] [%d] %s\n", $offset + 5, mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ if ($alternative) {
+ if (($row['id'] != $id) || (($row['label'] != $bind_value) && ($row['label'] != $alternative))) {
+ printf("[%03d] Testing '%s', '%s': expecting '%s'/'%s' (%s), got '%s'/'%s'\n",
+ $offset + 6, $bind_type, $sql_type,
+ $id, $bind_value, gettype($bind_value), $row['id'], $row['label']);
+ return false;
+ }
+ } else {
+ if (($row['id'] != $id) || ($row['label'] != $bind_value)) {
+ printf("[%03d] Testing '%s', '%s': expecting '%s'/'%s', got '%s'/'%s'\n",
+ $offset + 6, $bind_type, $sql_type,
+ $id, $bind_value, $row['id'], $row['label']);
+ return false;
+ }
+ }
+
+ mysqli_free_result($res);
+ return true;
+ }
+
+ function func_mysqli_stmt_bind_make_string($len) {
+
+ $ret = '';
+ for ($i = 0; $i < $len; $i++)
+ $ret .= chr(mt_rand(65, 90));
+
+ return $ret;
+ }
+
+ func_mysqli_stmt_bind_datatype($link, $engine, "i", "TINYINT", -11, 20);
+ func_mysqli_stmt_bind_datatype($link, $engine, "i", "TINYINT", NULL, 30);
+ func_mysqli_stmt_bind_datatype($link, $engine, "i", "TINYINT UNSIGNED", 1, 40);
+ func_mysqli_stmt_bind_datatype($link, $engine, "i", "TINYINT UNSIGNED", NULL, 50);
+
+ func_mysqli_stmt_bind_datatype($link, $engine, "i", "BOOL", 1, 60);
+ func_mysqli_stmt_bind_datatype($link, $engine, "i", "BOOL", NULL, 70);
+ func_mysqli_stmt_bind_datatype($link, $engine, "i", "BOOLEAN", 0, 80);
+ func_mysqli_stmt_bind_datatype($link, $engine, "i", "BOOLEAN", NULL, 90);
+
+ func_mysqli_stmt_bind_datatype($link, $engine, "i", "SMALLINT", -32768, 100);
+ func_mysqli_stmt_bind_datatype($link, $engine, "i", "SMALLINT", 32767, 110);
+ func_mysqli_stmt_bind_datatype($link, $engine, "i", "SMALLINT", NULL, 120);
+ func_mysqli_stmt_bind_datatype($link, $engine, "i", "SMALLINT UNSIGNED", 65535, 130);
+ func_mysqli_stmt_bind_datatype($link, $engine, "i", "SMALLINT UNSIGNED", NULL, 140);
+
+ func_mysqli_stmt_bind_datatype($link, $engine, "i", "MEDIUMINT", -8388608, 150);
+ func_mysqli_stmt_bind_datatype($link, $engine, "i", "MEDIUMINT", 8388607, 160);
+ func_mysqli_stmt_bind_datatype($link, $engine, "i", "MEDIUMINT", NULL, 170);
+ func_mysqli_stmt_bind_datatype($link, $engine, "i", "MEDIUMINT UNSIGNED", 16777215, 180);
+ func_mysqli_stmt_bind_datatype($link, $engine, "i", "MEDIUMINT UNSIGNED", NULL, 190);
+
+ func_mysqli_stmt_bind_datatype($link, $engine, "i", "INTEGER", -2147483648, 200);
+ func_mysqli_stmt_bind_datatype($link, $engine, "i", "INTEGER", 2147483647, 210);
+ func_mysqli_stmt_bind_datatype($link, $engine, "i", "INTEGER", NULL, 220);
+ func_mysqli_stmt_bind_datatype($link, $engine, "i", "INTEGER UNSIGNED", (defined("PHP_INT_MAX")) ? min(4294967295, PHP_INT_MAX) : 1, 230);
+ func_mysqli_stmt_bind_datatype($link, $engine, "d", "INTEGER UNSIGNED", 4294967295, 240);
+ func_mysqli_stmt_bind_datatype($link, $engine, "i", "INTEGER UNSIGNED", NULL, 250);
+
+ func_mysqli_stmt_bind_datatype($link, $engine, "i", "BIGINT", -1 * PHP_INT_MAX + 1, 260);
+ func_mysqli_stmt_bind_datatype($link, $engine, "i", "BIGINT", NULL, 270);
+ func_mysqli_stmt_bind_datatype($link, $engine, "i", "BIGINT", PHP_INT_MAX, 280);
+ func_mysqli_stmt_bind_datatype($link, $engine, "i", "BIGINT UNSIGNED", NULL, 290);
+
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "BIGINT", "-9223372036854775808", 900);
+ // ?? func_mysqli_stmt_bind_datatype($link, $engine, "d", "BIGINT", -9223372036854775808, 910);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "BIGINT UNSIGNED", "18446744073709551615", 920);
+
+/*
+ ??
+ func_mysqli_stmt_bind_datatype($link, $engine, "d", "FLOAT", -9223372036854775808 - 1.1, 300);
+ func_mysqli_stmt_bind_datatype($link, $engine, "d", "FLOAT UNSIGNED", 18446744073709551615 + 1.1, 320);
+ */
+ func_mysqli_stmt_bind_datatype($link, $engine, "d", "FLOAT", NULL, 310);
+ func_mysqli_stmt_bind_datatype($link, $engine, "d", "FLOAT UNSIGNED ", NULL, 330);
+ if (2147483647 == PHP_INT_MAX) {
+ func_mysqli_stmt_bind_datatype($link, $engine, "d", "FLOAT UNSIGNED", PHP_INT_MAX, 930, '2.14748e+09');
+ func_mysqli_stmt_bind_datatype($link, $engine, "d", "FLOAT", -1 * PHP_INT_MAX + 1, 940, '-2.14748e+09');
+ }
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "FLOAT", "-9223372036854775808", 300, '-9.22337e+18');
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "FLOAT UNSIGNED", "18446744073709551615", 320, '1.84467e+19');
+ func_mysqli_stmt_bind_datatype($link, $engine, "d", "FLOAT", -10.01, 950);
+ func_mysqli_stmt_bind_datatype($link, $engine, "d", "FLOAT UNSIGNED", 10.01, 960);
+
+ func_mysqli_stmt_bind_datatype($link, $engine, "d", "DOUBLE(10,2)", NULL, 350);
+ func_mysqli_stmt_bind_datatype($link, $engine, "d", "DOUBLE(10,2) UNSIGNED", NULL, 370);
+ func_mysqli_stmt_bind_datatype($link, $engine, "d", "DOUBLE(10,2)", -99999999.99, 340);
+ func_mysqli_stmt_bind_datatype($link, $engine, "d", "DOUBLE(10,2) UNSIGNED", 99999999.99, 360);
+
+ /*
+ func_mysqli_stmt_bind_datatype($link, $engine, "d", "DOUBLE(10,2)", -99999999.99, 340);
+ func_mysqli_stmt_bind_datatype($link, $engine, "d", "DOUBLE(10,2) UNSIGNED", 99999999.99, 360);
+ */
+ func_mysqli_stmt_bind_datatype($link, $engine, "d", "DECIMAL(10,2)", -99999999.99, 380);
+ func_mysqli_stmt_bind_datatype($link, $engine, "d", "DECIMAL(10,2)", NULL, 390);
+ func_mysqli_stmt_bind_datatype($link, $engine, "d", "DECIMAL(10,2)", 99999999.99, 400);
+ func_mysqli_stmt_bind_datatype($link, $engine, "d", "DECIMAL(10,2)", NULL, 410);
+
+ // don't care about date() strict TZ warnings...
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "DATE", @date('Y-m-d'), 420);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "DATE NOT NULL", @date('Y-m-d'), 430);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "DATE", NULL, 440);
+
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "DATETIME", @date('Y-m-d H:i:s'), 450);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "DATETIME NOT NULL", @date('Y-m-d H:i:s'), 460);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "DATETIME", NULL, 470);
+
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "TIMESTAMP", @date('Y-m-d H:i:s'), 480);
+
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "TIME", @date('H:i:s'), 490);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "TIME NOT NULL", @date('H:i:s'), 500);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "TIME", NULL, 510);
+
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "YEAR", @date('Y'), 520);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "YEAR NOT NULL", @date('Y'), 530);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "YEAR", NULL, 540);
+
+ $string255 = func_mysqli_stmt_bind_make_string(255);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "CHAR(1)", "a", 550);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "CHAR(255)", $string255, 560);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "CHAR(1) NOT NULL", "a", 570);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "CHAR(1)", NULL, 580);
+
+ $string65k = func_mysqli_stmt_bind_make_string(65535);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "VARCHAR(1)", "a", 590);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "VARCHAR(255)", $string255, 600);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "VARCHAR(65635)", $string65k, 610);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "VARCHAR(1) NOT NULL", "a", 620);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "VARCHAR(1)", NULL, 630);
+
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "BINARY(1)", "a", 640);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "BINARY(1)", chr(0), 650);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "BINARY(1) NOT NULL", "b", 660);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "BINARY(1)", NULL, 670);
+
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "VARBINARY(1)", "a", 680);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "VARBINARY(1)", chr(0), 690);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "VARBINARY(1) NOT NULL", "b", 700);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "VARBINARY(1)", NULL, 710);
+
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "TINYBLOB", "a", 720);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "TINYBLOB", chr(0), 730);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "TINYBLOB NOT NULL", "b", 740);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "TINYBLOB", NULL, 750);
+
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "TINYTEXT", "a", 760);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "TINYTEXT NOT NULL", "a", 770);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "TINYTEXT", NULL, 780);
+
+ // Note: you cannot insert any blob values this way. But you can check the API at least partly this way
+ // Extra BLOB tests are in mysqli_stmt_send_long()
+ func_mysqli_stmt_bind_datatype($link, $engine, "b", "BLOB", "", 790);
+ func_mysqli_stmt_bind_datatype($link, $engine, "b", "TEXT", "", 800);
+ func_mysqli_stmt_bind_datatype($link, $engine, "b", "MEDIUMBLOB", "", 810);
+ func_mysqli_stmt_bind_datatype($link, $engine, "b", "MEDIUMTEXT", "", 820);
+ func_mysqli_stmt_bind_datatype($link, $engine, "b", "LONGBLOB", "", 830);
+ func_mysqli_stmt_bind_datatype($link, $engine, "b", "LONGTEXT", "", 840);
+
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "ENUM('a', 'b')", "a", 850);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "ENUM('a', 'b')", NULL, 860);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "SET('a', 'b')", "a", 870);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "SET('a', 'b')", NULL, 880);
+
+ if (mysqli_get_server_version($link) >= 50600)
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "TIME", "13:27:34.123456", 890, "13:27:34");
+
+ $stmt = mysqli_stmt_init($link);
+ if (!mysqli_stmt_prepare($stmt, "INSERT INTO test(id, label) VALUES (?, ?)"))
+ printf("[2000] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = null;
+ $label = null;
+ if (true !== ($tmp = mysqli_stmt_bind_param($stmt, "is", $id, $label)))
+ printf("[2001] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ mysqli_stmt_execute($stmt);
+
+ if (true !== ($tmp = mysqli_stmt_bind_param($stmt, "is", $id, $label)))
+ printf("[2002] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ mysqli_stmt_close($stmt);
+ include("table.inc");
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[2003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_stmt_prepare($stmt, "INSERT INTO test(id, label) VALUES (?, ?)"))
+ printf("[2004] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = $label = null;
+ if (true !== ($tmp = $stmt->bind_param('is', $id, $label)))
+ printf("[2005] Expecting boolean/true got %s/%s, [%d] %s\n",
+ gettype($tmp), $tmp,
+ $stmt->errno, $stmt->error);
+
+ $id = 100; $label = 'z';
+ if (!$stmt->execute())
+ printf("[2006] [%d] %s\n", $stmt->errno, $stmt->error);
+
+ if (!$res = mysqli_query($link, "SELECT id, label FROM test WHERE id = 100"))
+ printf("[2007] Expecting record 100/z, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$row = mysqli_fetch_assoc($res))
+ printf("[2008] Expecting row, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if ($row['id'] != 100 || $row['label'] != 'z') {
+ printf("[2009] Row seems wrong, dumping record\n");
+ var_dump($row);
+ }
+ mysqli_free_result($res);
+
+ $value_list = array(array('id' => 101, 'label' => 'a'), array('id' => 102, 'label' => 'b'));
+ if (!mysqli_stmt_prepare($stmt, "INSERT INTO test(id, label) VALUES (?, ?)"))
+ printf("[2010] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ foreach ($value_list as $k => $values) {
+ if (!mysqli_stmt_bind_param($stmt, 'is', $values['id'], $values['label'])) {
+ printf("[2011] bind_param() failed for id = %d, [%d] %s\n",
+ $values['id'], mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ continue;
+ }
+ if (!$stmt->execute())
+ printf("[2012] [%d] execute() failed for id = %d, [%d] %s\n",
+ $values['id'], mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!$res = mysqli_query($link, sprintf("SELECT label FROM test WHERE id = %d", $values['id'])))
+ printf("[2013] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ if (!$row = mysqli_fetch_assoc($res))
+ printf("[2014] Cannot find row id = %d\n", $values['id']);
+ else if (isset($row['label']) && ($values['label'] != $row['label']))
+ printf("[2015] Expecting label = %s, got label = %s\n", $values['label'], $row['label']);
+
+ mysqli_free_result($res);
+ }
+
+ mysqli_stmt_close($stmt);
+ mysqli_close($link);
+
+ /* Check that the function alias exists. It's a deprecated function,
+ but we have not announce the removal so far, therefore we need to check for it */
+ if (!is_null($tmp = @mysqli_stmt_bind_param()))
+ printf("[021] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Warning: mysqli_stmt_bind_param(): Number of elements in type definition string doesn't match number of bind variables in %s on line %d
+
+Warning: mysqli_stmt_bind_param(): Number of elements in type definition string doesn't match number of bind variables in %s on line %d
+
+Warning: mysqli_stmt_bind_param(): Number of variables doesn't match number of parameters in prepared statement in %s on line %d
+
+Warning: mysqli_stmt_bind_param(): Number of elements in type definition string doesn't match number of bind variables in %s on line %d
+
+Warning: mysqli_stmt_bind_param(): Undefined fieldtype a (parameter 3) in %s on line %d
+
+Warning: mysqli_stmt_bind_param(): Undefined fieldtype a (parameter 4) in %s on line %d
+done!
diff --git a/ext/mysqli/tests/mysqli_stmt_bind_param_call_user_func.phpt b/ext/mysqli/tests/mysqli_stmt_bind_param_call_user_func.phpt
new file mode 100644
index 0000000..8f4a989
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_bind_param_call_user_func.phpt
@@ -0,0 +1,366 @@
+--TEST--
+mysqli_stmt_bind_param used with call_user_func_array() (see also bug #43568)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+// TODO remove once a decision has been made on call_user_func_array()
+if (version_compare(PHP_VERSION, '5.3.0-dev') == -1)
+ die("skip needs PHP 5.3.0-dev+, see http://bugs.php.net/bug.php?id=43568");
+?>
+--FILE--
+<?php
+ require('connect.inc');
+ require('table.inc');
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[001] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_stmt_prepare($stmt, 'SELECT id, label FROM test WHERE id = ?'))
+ printf("[002] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = 1;
+ if (!mysqli_stmt_bind_param($stmt, 'i', $id) ||
+ !mysqli_stmt_execute($stmt))
+ printf("[003] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = $label = null;
+ if (!mysqli_stmt_bind_result($stmt, $id, $label) ||
+ (true !== mysqli_stmt_fetch($stmt)))
+ printf("[004] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ print "Regular, procedural, using variables\n";
+ var_dump($id);
+ var_dump($label);
+
+ mysqli_stmt_close($stmt);
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[005] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_stmt_prepare($stmt, 'SELECT id, label FROM test WHERE id = ?'))
+ printf("[006] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $types = 'i';
+ $id = 1;
+ $params = array(
+ 0 => &$stmt,
+ 1 => &$types,
+ 2 => &$id
+ );
+ if (!call_user_func_array('mysqli_stmt_bind_param', $params))
+ printf("[007] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_execute($stmt))
+ printf("[008] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = $label = null;
+ if (!mysqli_stmt_bind_result($stmt, $id, $label) ||
+ (true !== mysqli_stmt_fetch($stmt)))
+ printf("[009] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ print "Call user func, procedural, using references for everything\n";
+ var_dump($id);
+ var_dump($label);
+
+ mysqli_stmt_close($stmt);
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[010] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_stmt_prepare($stmt, 'SELECT id, label FROM test WHERE id = ?'))
+ printf("[011] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $types = 'i';
+ $id = 1;
+ $params = array(
+ 0 => &$types,
+ 1 => &$id
+ );
+ if (!call_user_func_array(array($stmt, 'bind_param'), $params))
+ printf("[012] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_execute($stmt))
+ printf("[013] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = $label = null;
+ if (!mysqli_stmt_bind_result($stmt, $id, $label) ||
+ (true !== mysqli_stmt_fetch($stmt)))
+ printf("[014] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ print "Call user func, object oriented, using references for everything\n";
+ var_dump($id);
+ var_dump($label);
+
+ mysqli_stmt_close($stmt);
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[015] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_stmt_prepare($stmt, 'SELECT id, label FROM test WHERE id = ?'))
+ printf("[016] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $types = 'i';
+ $id = 1;
+ $params = array(
+ 0 => $types,
+ 1 => &$id
+ );
+ if (!call_user_func_array(array($stmt, 'bind_param'), $params))
+ printf("[017] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_execute($stmt))
+ printf("[018] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = $label = null;
+ if (!mysqli_stmt_bind_result($stmt, $id, $label) ||
+ (true !== mysqli_stmt_fetch($stmt)))
+ printf("[019] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ print "Call user func, object oriented, using variable for types. using references for bound parameter\n";
+ var_dump($id);
+ var_dump($label);
+
+ mysqli_stmt_close($stmt);
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[020] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_stmt_prepare($stmt, 'SELECT id, label FROM test WHERE id = ?'))
+ printf("[021] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = 1;
+ $params = array(
+ 0 => 'i',
+ 1 => &$id
+ );
+ if (!call_user_func_array(array($stmt, 'bind_param'), $params))
+ printf("[022] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_execute($stmt))
+ printf("[023] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = $label = null;
+ if (!mysqli_stmt_bind_result($stmt, $id, $label) ||
+ (true !== mysqli_stmt_fetch($stmt)))
+ printf("[024] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ print "Call user func, object oriented, using constant for types. using references for bound parameter\n";
+ var_dump($id);
+ var_dump($label);
+
+ mysqli_stmt_close($stmt);
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[025] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_stmt_prepare($stmt, 'SELECT id, label FROM test WHERE id = ?'))
+ printf("[026] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $types = 'i';
+ $id = 1;
+ $params = array(
+ 0 => &$stmt,
+ 1 => $types,
+ 2 => &$id
+ );
+ if (!call_user_func_array('mysqli_stmt_bind_param', $params))
+ printf("[027] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_execute($stmt))
+ printf("[028] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = $label = null;
+ if (!mysqli_stmt_bind_result($stmt, $id, $label) ||
+ (true !== mysqli_stmt_fetch($stmt)))
+ printf("[029] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ print "Call user func, procedural, using references for everything but using variable for types\n";
+ var_dump($id);
+ var_dump($label);
+
+ mysqli_stmt_close($stmt);
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[025] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_stmt_prepare($stmt, 'SELECT id, label FROM test WHERE id = ?'))
+ printf("[026] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $types = 'i';
+ $id = 1;
+ $params = array(
+ 0 => $stmt,
+ 1 => $types,
+ 2 => &$id
+ );
+ if (!call_user_func_array('mysqli_stmt_bind_param', $params))
+ printf("[027] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_execute($stmt))
+ printf("[028] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = $label = null;
+ if (!mysqli_stmt_bind_result($stmt, $id, $label) ||
+ (true !== mysqli_stmt_fetch($stmt)))
+ printf("[029] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ print "Call user func, procedural, using references for bound parameter, using variables for resource and types\n";
+ var_dump($id);
+ var_dump($label);
+
+ mysqli_stmt_close($stmt);
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[030] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_stmt_prepare($stmt, 'SELECT id, label FROM test WHERE id = ?'))
+ printf("[031] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $types = 'i';
+ $id = 1;
+ $params = array(
+ 0 => $stmt,
+ 1 => $types,
+ 2 => &$id
+ );
+ if (!call_user_func_array('mysqli_stmt_bind_param', $params))
+ printf("[032] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_execute($stmt))
+ printf("[033] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = $label = null;
+ if (!mysqli_stmt_bind_result($stmt, $id, $label) ||
+ (true !== mysqli_stmt_fetch($stmt)))
+ printf("[034] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ print "Call user func, procedural, using references for bound parameter, using variables for resource and types\n";
+ var_dump($id);
+ var_dump($label);
+
+ mysqli_stmt_close($stmt);
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[035] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_stmt_prepare($stmt, 'SELECT id, label FROM test WHERE id = ?'))
+ printf("[036] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = 1;
+ $params = array(
+ 0 => $stmt,
+ 1 => 'i',
+ 2 => &$id
+ );
+ if (!call_user_func_array('mysqli_stmt_bind_param', $params))
+ printf("[037] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_execute($stmt))
+ printf("[038] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = $label = null;
+ if (!mysqli_stmt_bind_result($stmt, $id, $label) ||
+ (true !== mysqli_stmt_fetch($stmt)))
+ printf("[039] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ print "Call user func, procedural, using references for bound parameter, using variable for resource, using constant for types\n";
+ var_dump($id);
+ var_dump($label);
+
+ mysqli_stmt_close($stmt);
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[040] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_stmt_prepare($stmt, 'SELECT id, label FROM test WHERE id = ?'))
+ printf("[041] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = 1;
+ if (!call_user_func_array('mysqli_stmt_bind_param', array($stmt, 'i', &$id)))
+ printf("[042] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_execute($stmt))
+ printf("[043] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = $label = null;
+ if (!mysqli_stmt_bind_result($stmt, $id, $label) ||
+ (true !== mysqli_stmt_fetch($stmt)))
+ printf("[044] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ print "Call user func, procedural, using references for bound parameter, using variable for resource, using constant for types, array\n";
+ var_dump($id);
+ var_dump($label);
+
+ //
+ // Any of those shall fail - see also bugs.php.net/43568
+ //
+ mysqli_stmt_close($stmt);
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[045] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_stmt_prepare($stmt, 'SELECT id, label FROM test WHERE id = ?'))
+ printf("[046] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = 1;
+ $params = array(
+ 0 => 'i',
+ 1 => &$id
+ );
+ if (!call_user_func_array(array($stmt, 'bind_param'), $params))
+ printf("[047] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_execute($stmt))
+ printf("[048] [%d] (Message might vary with MySQL Server version, e.g. No data supplied for parameters in prepared statement)\n", mysqli_stmt_errno($stmt));
+
+ mysqli_stmt_close($stmt);
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[049] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_stmt_prepare($stmt, 'SELECT id, label FROM test WHERE id = ?'))
+ printf("[050] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $types = 'i';
+ $id = 1;
+ $params = array(
+ 0 => $stmt,
+ 1 => 'i',
+ 2 => &$id
+ );
+ if (!call_user_func_array('mysqli_stmt_bind_param', $params))
+ printf("[051] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_execute($stmt))
+ printf("[052] [%d] (Message might vary with MySQL Server version, e.g. No data supplied for parameters in prepared statement)\n", mysqli_stmt_errno($stmt));
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Regular, procedural, using variables
+int(1)
+%unicode|string%(1) "a"
+Call user func, procedural, using references for everything
+int(1)
+%unicode|string%(1) "a"
+Call user func, object oriented, using references for everything
+int(1)
+%unicode|string%(1) "a"
+Call user func, object oriented, using variable for types. using references for bound parameter
+int(1)
+%unicode|string%(1) "a"
+Call user func, object oriented, using constant for types. using references for bound parameter
+int(1)
+%unicode|string%(1) "a"
+Call user func, procedural, using references for everything but using variable for types
+int(1)
+%unicode|string%(1) "a"
+Call user func, procedural, using references for bound parameter, using variables for resource and types
+int(1)
+%unicode|string%(1) "a"
+Call user func, procedural, using references for bound parameter, using variables for resource and types
+int(1)
+%unicode|string%(1) "a"
+Call user func, procedural, using references for bound parameter, using variable for resource, using constant for types
+int(1)
+%unicode|string%(1) "a"
+Call user func, procedural, using references for bound parameter, using variable for resource, using constant for types, array
+int(1)
+%unicode|string%(1) "a"
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_bind_param_check_param_no_change.phpt b/ext/mysqli/tests/mysqli_stmt_bind_param_check_param_no_change.phpt
new file mode 100644
index 0000000..03d1590
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_bind_param_check_param_no_change.phpt
@@ -0,0 +1,110 @@
+--TEST--
+mysqli_stmt_bind_param() - checking whether the parameters are modified (bug#44390)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require('table.inc');
+ $link->set_charset('latin1');
+
+ class foo {
+ // @var $bar string
+ public $bar;
+ }
+
+ $foo = new foo;
+ $foo->bar = "фубар";
+
+ echo "Test 1:\n";
+ $stmt = $link->prepare("SELECT ? FOO");
+ var_dump($foo); // here you can see the bar member var beeing a string
+ $stmt->bind_param("s", $foo->bar);
+ var_dump($foo); // this will show $foo->bar beeing a reference string
+ $stmt->bind_result($one);
+ $stmt->execute();
+ $stmt->fetch();
+ $stmt->free_result();
+ echo("$one\n\n");
+
+ // it is getting worse. Binding the same var twice with different
+ // types you can get unexpected results (e.g. binary trash for the
+ // string and misc data for the integer. See next 2 tests.
+
+ echo "Test 2:\n";
+ $stmt = $link->prepare("SELECT ? FOO, ? BAR");
+ var_dump($foo);
+ $stmt->bind_param("si", $foo->bar, $foo->bar);
+ echo "---\n";
+ var_dump($foo);
+ echo "---\n";
+ $stmt->execute();
+ var_dump($foo);
+ echo "---\n";
+ $stmt->bind_result($one, $two);
+ $stmt->fetch();
+ $stmt->free_result();
+ echo("$one - $two\n\n");
+
+
+ echo "Test 3:\n";
+ $stmt = $link->prepare("SELECT ? FOO, ? BAR");
+ var_dump($foo);
+ $stmt->bind_param("is", $foo->bar, $foo->bar);
+ var_dump($foo);
+ $stmt->bind_result($one, $two);
+ $stmt->execute();
+ $stmt->fetch();
+ $stmt->free_result();
+ echo("$one - $two\n\n");
+ echo "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Test 1:
+object(foo)#%d (1) {
+ [%u|b%"bar"]=>
+ %unicode|string%(%d) "фубар"
+}
+object(foo)#%d (1) {
+ [%u|b%"bar"]=>
+ &%unicode|string%(%d) "фубар"
+}
+фубар
+
+Test 2:
+object(foo)#%d (1) {
+ [%u|b%"bar"]=>
+ %unicode|string%(%d) "фубар"
+}
+---
+object(foo)#%d (1) {
+ [%u|b%"bar"]=>
+ &%unicode|string%(%d) "фубар"
+}
+---
+object(foo)#%d (1) {
+ [%u|b%"bar"]=>
+ &%unicode|string%(%d) "фубар"
+}
+---
+фубар - 0
+
+Test 3:
+object(foo)#%d (1) {
+ [%u|b%"bar"]=>
+ %unicode|string%(%d) "фубар"
+}
+object(foo)#%d (1) {
+ [%u|b%"bar"]=>
+ &%unicode|string%(%d) "фубар"
+}
+0 - фубар
+
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_bind_param_many_columns.phpt b/ext/mysqli/tests/mysqli_stmt_bind_param_many_columns.phpt
new file mode 100644
index 0000000..29a5ee3
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_bind_param_many_columns.phpt
@@ -0,0 +1,103 @@
+--TEST--
+mysqli_stmt_bind_param() - Binding with very high number of columns
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--INI--
+memory_limit=256M
+--FILE--
+<?php
+ /*
+ The way we test the INSERT and data types overlaps with
+ the mysqli_stmt_bind_result test in large parts. There is only
+ one difference. This test uses mysqli_query()/mysqli_fetch_assoc() to
+ fetch the inserted values. This way we test
+ mysqli_query()/mysqli_fetch_assoc() for all possible data types
+ in this file and we test mysqli_stmt_bind_result() in the other
+ test -- therefore the "duplicate" makes some sense to me.
+ */
+ require_once("connect.inc");
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ printf("[001] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+ exit(1);
+ }
+
+ $cols = 2500;
+
+ list($old_max_allowed_packet) = $link->query("SELECT @@max_allowed_packet")->fetch_row();
+ if (!$link->query("SET GLOBAL max_allowed_packet=(2<<29)")) {
+ if (1227 == mysqli_errno($link)) {
+ /* [1227] Access denied; you need the SUPER privilege for this operation */
+ $cols = 10;
+ } else {
+ $cols = 10;
+ printf("[002] Failed to set max_allowed_packet the test table: [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+ }
+ mysqli_close($link);
+
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ printf("Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+ exit(1);
+ }
+
+ if (!mysqli_query($link, 'DROP TABLE IF EXISTS test')) {
+ printf("Failed to drop old test table: [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ exit(1);
+ }
+
+ $str = array();
+ for ($i = 1; $i <= $cols; $i++) {
+ $str[] ="a$i BLOB";
+ }
+ $link->query("CREATE TABLE test(" . implode(" , ", $str) . ") ENGINE=MyISAM");
+ if (mysqli_errno($link)) {
+ printf("Failed to create the test table: [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ die("");
+ }
+ $stmt = $link->prepare("INSERT INTO test VALUES(".str_repeat("?, ", $cols-1) . "?)");
+ var_dump($stmt->id);
+ $s = str_repeat("a", 2 << 12);
+ $eval_str="\$stmt->bind_param(\"".str_repeat("s",$cols)."\", ";
+ for ($i = 1; $i < $cols; $i++) {
+ $eval_str.="\$s,";
+ }
+ $eval_str.="\$s";
+ $eval_str.=");";
+ eval($eval_str);
+ printf("executing\n");
+ if (!$stmt->execute()) {
+ printf("failed");
+ printf("Failed to execute: [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ } else {
+ var_dump(true);
+ }
+
+ mysqli_stmt_close($stmt);
+
+
+ if (!$link->query("SET GLOBAL max_allowed_packet=$old_max_allowed_packet")) {
+ if (1227 != mysqli_errno($link))
+ printf("Failed to set max_allowed_packet the test table: [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ mysqli_close($link);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+int(1)
+executing
+bool(true)
+done!
diff --git a/ext/mysqli/tests/mysqli_stmt_bind_param_references.phpt b/ext/mysqli/tests/mysqli_stmt_bind_param_references.phpt
new file mode 100644
index 0000000..91cb9d0
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_bind_param_references.phpt
@@ -0,0 +1,207 @@
+--TEST--
+mysqli_stmt_bind_param() - playing with references
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require('table.inc');
+
+ function findRow($offset, $link, $id, $label) {
+
+ $sql = sprintf("SELECT id, label FROM test WHERE id = '%d' AND label = '%s'",
+ $id, $label);
+ if (!$res = mysqli_query($link, $sql)) {
+ printf("[%03d + 1] %s failed, [%d] %s\n",
+ $offset, $sql, mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+ if (!$row = mysqli_fetch_assoc($res)) {
+ printf("[%03d + 2] fetch for %s failed, [%d] %s\n",
+ $offset, $sql, mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ mysqli_free_result($res);
+ if ($row['id'] != $id) {
+ printf("[%03d + 3] Expecting %s/%s got %s/%s\n",
+ $offset, gettype($id), $id,
+ gettype($row['id']), $row['id']
+ );
+ return false;
+ }
+
+ if ($row['label'] != $label) {
+ printf("[%03d + 4] Expecting %s/%s got %s/%s\n",
+ $offset, gettype($label), $label,
+ gettype($row['label']), $row['label']
+ );
+ return false;
+ }
+
+ $sql = sprintf("DELETE FROM test WHERE id = '%d' AND label = '%s'",
+ $id, $label);
+ if (!mysqli_query($link, $sql)) {
+ printf("[%03d + 5] %s failed, [%d] %s\n",
+ $offset, $sql, mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ return true;
+ }
+ // or we will get dups around [28]
+ mysqli_query($link, "ALTER TABLE test DROP PRIMARY KEY");
+
+ $stmt = mysqli_stmt_init($link);
+ if (!mysqli_stmt_prepare($stmt, "INSERT INTO test(id, label) VALUES (?, ?)"))
+ printf("[001] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = 100;
+ $label = 'v';
+ if (true !== ($tmp = mysqli_stmt_bind_param($stmt, "is", $id, $label)))
+ printf("[002] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (true !== mysqli_stmt_execute($stmt))
+ printf("[003] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ // no need to check the return value, will bail and make EXPECTF fail if need be
+ findRow(4, $link, $id, $label);
+
+ $id++;
+ $label_ref = &$label;
+ $label = 'w';
+ if (true !== ($tmp = mysqli_stmt_bind_param($stmt, "is", $id, $label_ref)))
+ printf("[005] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (true !== mysqli_stmt_execute($stmt))
+ printf("[006] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ findRow(7, $link, $id, $label_ref);
+
+ $id++;
+ $label_ref_ref = &$label_ref;
+ $label = 'x';
+
+ if (true !== ($tmp = mysqli_stmt_bind_param($stmt, "is", $id, $label_ref_ref)))
+ printf("[007] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (true !== mysqli_stmt_execute($stmt))
+ printf("[008] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ findRow(9, $link, $id, $label_ref_ref);
+
+ $id = 9;
+ $label = $id;
+ $label_num = &$label;
+
+ if (true !== ($tmp = mysqli_stmt_bind_param($stmt, "is", $id, $label_num)))
+ printf("[010] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (true !== mysqli_stmt_execute($stmt))
+ printf("[011] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ findRow(12, $link, $id, $label_num);
+
+ $label_num = &$id;
+ if (true !== ($tmp = mysqli_stmt_bind_param($stmt, "is", $id, $label_num)))
+ printf("[013] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (true !== mysqli_stmt_execute($stmt))
+ printf("[014] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ findRow(15, $link, $id, $label_num);
+
+ $label = 9;
+ $id = &$label;
+
+ if (true !== ($tmp = mysqli_stmt_bind_param($stmt, "is", $id, $label)))
+ printf("[015] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (true !== mysqli_stmt_execute($stmt))
+ printf("[016] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ findRow(17, $link, $id, $label);
+
+ $base = 9;
+ $id = &$base;
+ $label = &$id;
+
+ if (true !== ($tmp = mysqli_stmt_bind_param($stmt, "is", $id, $label)))
+ printf("[018] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (true !== mysqli_stmt_execute($stmt))
+ printf("[019] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ findRow(20, $link, $id, $label);
+
+ $id_ref = &$id;
+ $label_ref = &$label;
+
+ if (true !== ($tmp = mysqli_stmt_bind_param($stmt, "is", $id_ref, $label_ref)))
+ printf("[021] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (true !== mysqli_stmt_execute($stmt))
+ printf("[022] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ findRow(23, $link, $id_ref, $label_ref);
+
+ $id_ref_ref = &$GLOBALS['id_ref'];
+ $label_ref_ref = &$GLOBALS['label_ref_ref'];
+
+ if (true !== ($tmp = mysqli_stmt_bind_param($stmt, "is", $id_ref_ref, $label_ref_ref)))
+ printf("[024] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (true !== mysqli_stmt_execute($stmt))
+ printf("[025] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ findRow(26, $link, $id_ref_ref, $label_ref_ref);
+
+ unset($id);
+ unset($label);
+ $id = 102;
+ $label = new stdClass();
+ $label->label = 'y';
+ $id_ref = &$GLOBALS['id'];
+ $label_ref = &$label->label;
+ if (true !== ($tmp = mysqli_stmt_bind_param($stmt, "is", $id_ref, $label_ref)))
+ printf("[027] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+ if (true !== @mysqli_stmt_execute($stmt))
+ printf("[028] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ findRow(29, $link, $id_ref, $label_ref);
+
+ $id = 103;
+ $label_a = &$label_b;
+ $label_b = &$label_a;
+ $label_a = 'z';
+
+ if (true !== ($tmp = mysqli_stmt_bind_param($stmt, "is", $id, $label_b)))
+ printf("[030] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (true !== mysqli_stmt_execute($stmt))
+ printf("[031] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ findRow(32, $link, $id, $label_b);
+
+ class foo {
+ public $foo;
+ function foo() {
+ $this->foo = &$this->bar;
+ }
+ }
+ class bar extends foo {
+ public $bar = 'v';
+ }
+ $bar = new bar();
+ $id++;
+ $label = &$GLOBALS['bar']->foo;
+
+ if (true !== ($tmp = mysqli_stmt_bind_param($stmt, "is", $id, $label)))
+ printf("[033] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (true !== mysqli_stmt_execute($stmt))
+ printf("[034] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ findRow(35, $link, $id, $label);
+
+ mysqli_stmt_close($stmt);
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_bind_param_type_juggling.phpt b/ext/mysqli/tests/mysqli_stmt_bind_param_type_juggling.phpt
new file mode 100644
index 0000000..daab40c
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_bind_param_type_juggling.phpt
@@ -0,0 +1,127 @@
+--TEST--
+mysqli_stmt_bind_param() - binding variable twice
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require('table.inc');
+
+ function bind_twice($link, $engine, $sql_type1, $sql_type2, $bind_type1, $bind_type2, $bind_value1, $bind_value2, $offset) {
+
+ if (!mysqli_query($link, "DROP TABLE IF EXISTS test")) {
+ printf("[%03d + 1] [%d] %s\n", $offset, mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+ mysqli_autocommit($link, true);
+
+ $sql = sprintf("CREATE TABLE test(col1 %s, col2 %s) ENGINE=%s", $sql_type1, $sql_type2, $engine);
+ if (!mysqli_query($link, $sql)) {
+ printf("[%03d + 2] [%d] %s\n", $offset, mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ if (!$stmt = mysqli_stmt_init($link)) {
+ printf("[%03d + 3] [%d] %s\n", $offset, mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ if (!mysqli_stmt_prepare($stmt, "INSERT INTO test(col1, col2) VALUES (?, ?)")) {
+ printf("[%03d + 4] [%d] %s\n", $offset, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ return false;
+ }
+
+ if (!mysqli_stmt_bind_param($stmt, $bind_type1 . $bind_type2, $bind_value1, $bind_value1)) {
+ printf("[%03d + 5] [%d] %s\n", $offset, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ return false;
+ }
+
+ if (!mysqli_stmt_execute($stmt)) {
+ printf("[%03d + 6] [%d] %s\n", $offset, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ return false;
+ }
+
+ if (!mysqli_stmt_bind_param($stmt, $bind_type1 . $bind_type2, $bind_value1, $bind_value2)) {
+ printf("[%03d + 7] [%d] %s\n", $offset, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ return false;
+ }
+ if (!mysqli_stmt_execute($stmt)) {
+ printf("[%03d + 8] [%d] %s\n", $offset, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ return false;
+ }
+
+ mysqli_stmt_close($stmt);
+ if (!$res = mysqli_query($link, "SELECT col1, col2 FROM test")) {
+ printf("[%03d + 9] [%d] %s\n", $offset, mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ if (2 !== ($tmp = mysqli_num_rows($res))) {
+ printf("[%03d + 10] Expecting 2 rows, got %d rows [%d] %s\n", $offset, $tmp, mysqli_errno($link), mysqli_error($link));
+ }
+
+ $row = mysqli_fetch_assoc($res);
+ if (($row['col1'] != $bind_value1) || ($row['col2'] != $bind_value1)) {
+ printf("[%03d + 11] Expecting col1 = %s, col2 = %s got col1 = %s, col2 = %s - [%d] %s\n",
+ $offset, $bind_value1, $bind_value1,
+ $row['col1'], $row['col2'],
+ mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ $row = mysqli_fetch_assoc($res);
+ if (($row['col1'] != $bind_value1) || ($row['col2'] != $bind_value2)) {
+ printf("[%03d + 12] Expecting col1 = %s, col2 = %s got col1 = %s, col2 = %s - [%d] %s\n",
+ $offset, $bind_value1, $bind_value2,
+ $row['col1'], $row['col2'],
+ mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+ mysqli_free_result($res);
+ return true;
+ }
+
+ bind_twice($link, $engine, 'CHAR(1)', 'CHAR(1)', 's', 's', 'a', 'b', 10);
+ bind_twice($link, $engine, 'INT', 'INT', 'i', 'i', 1, 2, 20);
+ bind_twice($link, $engine, 'FLOAT', 'FLOAT', 'd', 'd', 1.01, 1.02, 30);
+
+ /* type juggling - note that int->char works */
+ bind_twice($link, $engine, 'CHAR(1)', 'CHAR(1)', 's', 's', 1, 2, 40);
+ /* type juggling - note that string->integer works */
+ bind_twice($link, $engine, 'INT', 'INT', 'i', 'i', '1', '2', 50);
+ /* type juggling - note that string->float works*/
+ bind_twice($link, $engine, 'FLOAT', 'FLOAT', 'd', 'd', '1.01', '1.02', 60);
+
+ /* now, let's have two columns of different type and do type juggling */
+ /*
+ what the test will do is:
+ 1) col1 INT, col2 CHAR(1)
+ 2) bind_param('is', 1, 1)
+ 3) execute()
+ 4) bind_param('is', 1, 'a')
+ 5) execute()
+
+ col1 INT, col2 INT
+ bind_param('ii', '1', '2') --> OK (int column, string value)
+ bind_param('ii', 1, 2) --> OK (int column, int value)
+ col1 CHAR(1), col2 CHAR(2)
+ bind_param('ss', 1, 2) --> OK (string column, int value)
+
+ So, what about:
+ col1 INT, COL2 CHAR(1)
+ bind_param('is', 1, 1) ---> ??
+ */
+ bind_twice($link, $engine, 'INT', 'CHAR(1)', 'i', 's', 1, 'a', 70);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_bind_result.phpt b/ext/mysqli/tests/mysqli_stmt_bind_result.phpt
new file mode 100644
index 0000000..553e71a
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_bind_result.phpt
@@ -0,0 +1,331 @@
+--TEST--
+mysqli_stmt_bind_result()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $hint_str_or_unicode = (version_compare(PHP_VERSION, '5.9.9', '>') == 1) ? "unicode":"string";
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_stmt_bind_result()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_bind_result($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ $stmt = mysqli_stmt_init($link);
+ if (!mysqli_stmt_prepare($stmt, "SELECT id, label FROM test ORDER BY id LIMIT 1"))
+ printf("[002a] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!is_null($tmp = @mysqli_stmt_bind_result($stmt)))
+ printf("[002b] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_stmt_close($stmt);
+ $stmt = mysqli_stmt_init($link);
+
+ $id = null;
+ $label = null;
+ $foo = null;
+
+ if (!is_null($tmp = mysqli_stmt_bind_result($stmt)))
+ printf("[003] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_prepare($stmt, "SELECT id, label FROM test ORDER BY id LIMIT 1"))
+ printf("[004] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (false !== ($tmp = mysqli_stmt_bind_result($stmt, $id)))
+ printf("[005] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (true !== ($tmp = mysqli_stmt_bind_result($stmt, $id, $label)))
+ printf("[006] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (false !== ($tmp = mysqli_stmt_bind_result($stmt, $id, $label, $foo)))
+ printf("[007] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_execute($stmt))
+ printf("[008] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ while (mysqli_stmt_fetch($stmt)) {
+ var_dump($id);
+ var_dump($label);
+ }
+ mysqli_stmt_close($stmt);
+
+
+ function func_mysqli_stmt_bind_result($link, $engine, $bind_type, $sql_type, $bind_value, $offset, $type_hint = null) {
+
+ if (!mysqli_query($link, "DROP TABLE IF EXISTS test")) {
+ printf("[%04d] [%d] %s\n", $offset, mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ if (!mysqli_query($link, sprintf("CREATE TABLE test(id INT, label %s, PRIMARY KEY(id)) ENGINE = %s", $sql_type, $engine))) {
+ // don't bail - column type might not be supported by the server, ignore this
+ return false;
+ }
+
+ if (!$stmt = mysqli_stmt_init($link)) {
+ printf("[%04d] [%d] %s\n", $offset + 1, mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ if (!mysqli_stmt_prepare($stmt, "INSERT INTO test(id, label) VALUES (?, ?)")) {
+ printf("[%04d] [%d] %s\n", $offset + 2, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ return false;
+ }
+
+ $id = null;
+ if (!mysqli_stmt_bind_param($stmt, "i" . $bind_type, $id, $bind_value)) {
+ printf("[%04d] [%d] %s\n", $offset + 3, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ mysqli_stmt_close($stmt);
+ return false;
+ }
+
+ for ($id = 1; $id < 4; $id++) {
+ if (!mysqli_stmt_execute($stmt)) {
+ printf("[%04d] [%d] %s\n", $offset + 3 + $id, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ mysqli_stmt_close($stmt);
+ return false;
+ }
+ }
+ mysqli_stmt_close($stmt);
+
+ $stmt = mysqli_stmt_init($link);
+
+ if (!mysqli_stmt_prepare($stmt, "SELECT id, label FROM test")) {
+ printf("[%04d] [%d] %s\n", $offset + 7, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ mysqli_stmt_close($stmt);
+ return false;
+ }
+
+ if (!mysqli_stmt_execute($stmt)) {
+ printf("[%04d] [%d] %s\n", $offset + 8, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ mysqli_stmt_close($stmt);
+ return false;
+ }
+
+ $result = mysqli_stmt_result_metadata($stmt);
+
+ $bind_res = null;
+ if (!mysqli_stmt_bind_result($stmt, $id, $bind_res)) {
+ printf("[%04d] [%d] %s\n", $offset + 9, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ mysqli_stmt_close($stmt);
+ return false;
+ }
+ $num = 0;
+ $fields = mysqli_fetch_fields($result);
+
+ while (mysqli_stmt_fetch($stmt)) {
+ if (!gettype($bind_res)=="unicode") {
+ if ($bind_res !== $bind_value && (!$type_hint || ($type_hint !== gettype($bind_res)))) {
+ printf("[%04d] [%d] Expecting %s/'%s' [type hint = %s], got %s/'%s'\n",
+ $offset + 10, $num,
+ gettype($bind_value), $bind_value, $type_hint,
+ gettype($bind_res), $bind_res);
+ mysqli_stmt_close($stmt);
+ return false;
+ }
+ }
+ $num++;
+ }
+
+ if ($num != 3) {
+ printf("[%04d] [%d] %s, expecting 3 results, got only %d results\n",
+ $offset + 11, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt), $num);
+ mysqli_stmt_close($stmt);
+ return false;
+ }
+
+ mysqli_stmt_close($stmt);
+ return true;
+ }
+
+
+ function func_mysqli_stmt_bind_make_string($len) {
+
+ $ret = '';
+ for ($i = 0; $i < $len; $i++)
+ $ret .= chr(mt_rand(65, 90));
+
+ return $ret;
+ }
+
+ func_mysqli_stmt_bind_result($link, $engine, "i", "TINYINT", -11, 20);
+ func_mysqli_stmt_bind_result($link, $engine, "i", "TINYINT", NULL, 40);
+ func_mysqli_stmt_bind_result($link, $engine, "i", "TINYINT UNSIGNED", 1, 60);
+ func_mysqli_stmt_bind_result($link, $engine, "i", "TINYINT UNSIGNED", NULL, 80);
+
+ func_mysqli_stmt_bind_result($link, $engine, "i", "BOOL", 1, 100);
+ func_mysqli_stmt_bind_result($link, $engine, "i", "BOOL", NULL, 120);
+ func_mysqli_stmt_bind_result($link, $engine, "i", "BOOLEAN", 0, 140);
+ func_mysqli_stmt_bind_result($link, $engine, "i", "BOOLEAN", NULL, 160);
+
+ func_mysqli_stmt_bind_result($link, $engine, "i", "SMALLINT", -32768, 180);
+ func_mysqli_stmt_bind_result($link, $engine, "i", "SMALLINT", 32767, 200);
+ func_mysqli_stmt_bind_result($link, $engine, "i", "SMALLINT", NULL, 220);
+ func_mysqli_stmt_bind_result($link, $engine, "i", "SMALLINT UNSIGNED", 65535, 240);
+ func_mysqli_stmt_bind_result($link, $engine, "i", "SMALLINT UNSIGNED", NULL, 260);
+
+ func_mysqli_stmt_bind_result($link, $engine, "d", "MEDIUMINT", -8388608, 280, "integer");
+ func_mysqli_stmt_bind_result($link, $engine, "d", "MEDIUMINT", 8388607, 300, "integer");
+ func_mysqli_stmt_bind_result($link, $engine, "d", "MEDIUMINT", NULL, 320);
+ func_mysqli_stmt_bind_result($link, $engine, "d", "MEDIUMINT UNSIGNED", 16777215, 340, "integer");
+ func_mysqli_stmt_bind_result($link, $engine, "d", "MEDIUMINT UNSIGNED", NULL, 360);
+
+ func_mysqli_stmt_bind_result($link, $engine, "i", "INTEGER", (defined("PHP_INT_MAX")) ? max(-1 * PHP_INT_MAX + 1, -2147483648) : 1, 380);
+ func_mysqli_stmt_bind_result($link, $engine, "i", "INTEGER", -2147483647, 400, "integer");
+ func_mysqli_stmt_bind_result($link, $engine, "i", "INTEGER", (defined("PHP_INT_MAX")) ? min(2147483647, PHP_INT_MAX) : 1, 420);
+ func_mysqli_stmt_bind_result($link, $engine, "i", "INTEGER", NULL, 440);
+ func_mysqli_stmt_bind_result($link, $engine, "i", "INTEGER UNSIGNED", (defined("PHP_INT_MAX")) ? min(4294967295, 2147483647) : 1, 460);
+ func_mysqli_stmt_bind_result($link, $engine, "i", "INTEGER UNSIGNED", 4294967295, 480, (defined("PHP_INT_MAX") && (4294967295 > PHP_INT_MAX)) ? "string" : null);
+ func_mysqli_stmt_bind_result($link, $engine, "i", "INTEGER UNSIGNED", NULL, 500);
+
+ /* test is broken too: we bind "integer" but value is a float
+ func_mysqli_stmt_bind_result($link, $engine, "i", "BIGINT", -9223372036854775808, 520);
+ func_mysqli_stmt_bind_result($link, $engine, "i", "BIGINT UNSIGNED", 18446744073709551615, 560);
+ */
+ func_mysqli_stmt_bind_result($link, $engine, "i", "BIGINT", NULL, 540);
+ func_mysqli_stmt_bind_result($link, $engine, "i", "BIGINT UNSIGNED", NULL, 580);
+ func_mysqli_stmt_bind_result($link, $engine, "i", "BIGINT", -1, 1780);
+ func_mysqli_stmt_bind_result($link, $engine, "i", "BIGINT UNSIGNED", 1, 1800);
+ func_mysqli_stmt_bind_result($link, $engine, "i", "BIGINT", -1 * PHP_INT_MAX + 1, 1820);
+ func_mysqli_stmt_bind_result($link, $engine, "i", "BIGINT UNSIGNED", PHP_INT_MAX, 1840);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "BIGINT UNSIGNED", "18446744073709551615", 1860);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "BIGINT", "-9223372036854775808", 1880);
+
+ func_mysqli_stmt_bind_result($link, $engine, "d", "FLOAT", -9223372036854775808 - 1.1, 600);
+ func_mysqli_stmt_bind_result($link, $engine, "d", "FLOAT", NULL, 620);
+ func_mysqli_stmt_bind_result($link, $engine, "d", "FLOAT UNSIGNED", 18446744073709551615 + 1.1, 640);
+ func_mysqli_stmt_bind_result($link, $engine, "d", "FLOAT UNSIGNED ", NULL, 660);
+
+ // Yes, we need the temporary variable. The PHP casting will fouls us otherwise.
+ $tmp = strval('-99999999.99');
+ func_mysqli_stmt_bind_result($link, $engine, "d", "DOUBLE(10,2)", $tmp, 680, "string");
+ func_mysqli_stmt_bind_result($link, $engine, "d", "DOUBLE(10,2)", NULL, 700);
+ $tmp = strval('99999999.99');
+ func_mysqli_stmt_bind_result($link, $engine, "d", "DOUBLE(10,2) UNSIGNED", $tmp , 720, "string");
+ func_mysqli_stmt_bind_result($link, $engine, "d", "DOUBLE(10,2) UNSIGNED", NULL, 740);
+ $tmp = strval('-99999999.99');
+ func_mysqli_stmt_bind_result($link, $engine, "d", "DECIMAL(10,2)", $tmp, 760, "string");
+ func_mysqli_stmt_bind_result($link, $engine, "d", "DECIMAL(10,2)", NULL, 780);
+ $tmp = strval('99999999.99');
+ func_mysqli_stmt_bind_result($link, $engine, "d", "DECIMAL(10,2)", $tmp, 800, "string");
+ func_mysqli_stmt_bind_result($link, $engine, "d", "DECIMAL(10,2)", NULL, 820);
+
+ // don't care about date() strict TZ warnings...
+ func_mysqli_stmt_bind_result($link, $engine, "s", "DATE", @date('Y-m-d'), 840);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "DATE NOT NULL", @date('Y-m-d'), 860);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "DATE", NULL, 880);
+
+ func_mysqli_stmt_bind_result($link, $engine, "s", "DATETIME", @date('Y-m-d H:i:s'), 900);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "DATETIME NOT NULL", @date('Y-m-d H:i:s'), 920);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "DATETIME", NULL, 940);
+
+ func_mysqli_stmt_bind_result($link, $engine, "s", "TIMESTAMP", @date('Y-m-d H:i:s'), 960);
+
+ func_mysqli_stmt_bind_result($link, $engine, "s", "TIME", @date('H:i:s'), 980);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "TIME NOT NULL", @date('H:i:s'), 1000);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "TIME", NULL, 1020);
+
+ $tmp = intval(@date('Y'));
+ func_mysqli_stmt_bind_result($link, $engine, "s", "YEAR", $tmp, 1040, "integer");
+ func_mysqli_stmt_bind_result($link, $engine, "s", "YEAR NOT NULL", $tmp, 1060, "integer");
+ func_mysqli_stmt_bind_result($link, $engine, "s", "YEAR", NULL, 1080);
+
+ $string255 = func_mysqli_stmt_bind_make_string(255);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "CHAR(1)", "a", 1110, $hint_str_or_unicode);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "CHAR(255)", $string255, 1120, $hint_str_or_unicode);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "CHAR(1) NOT NULL", "a", 1140, $hint_str_or_unicode);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "CHAR(1)", NULL, 1160);
+
+ $string65k = func_mysqli_stmt_bind_make_string(65535);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "VARCHAR(1)", "a", 1180, $hint_str_or_unicode);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "VARCHAR(255)", $string255, 1200, $hint_str_or_unicode);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "VARCHAR(65635)", $string65k, 1220, $hint_str_or_unicode);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "VARCHAR(1) NOT NULL", "a", 1240, $hint_str_or_unicode);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "VARCHAR(1)", NULL, 1260);
+
+ func_mysqli_stmt_bind_result($link, $engine, "s", "BINARY(1)", "a", 1280);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "BINARY(1)", chr(0), 1300);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "BINARY(1) NOT NULL", "b", 1320);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "BINARY(1)", NULL, 1340);
+
+ func_mysqli_stmt_bind_result($link, $engine, "s", "VARBINARY(1)", "a", 1360);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "VARBINARY(1)", chr(0), 1380);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "VARBINARY(1) NOT NULL", "b", 1400);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "VARBINARY(1)", NULL, 1420);
+
+ func_mysqli_stmt_bind_result($link, $engine, "s", "TINYBLOB", "a", 1440);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "TINYBLOB", chr(0), 1460);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "TINYBLOB NOT NULL", "b", 1480);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "TINYBLOB", NULL, 1500);
+
+ func_mysqli_stmt_bind_result($link, $engine, "s", "TINYTEXT", "a", 1520, $hint_str_or_unicode);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "TINYTEXT NOT NULL", "a", 1540, $hint_str_or_unicode);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "TINYTEXT", NULL, 1560, $hint_str_or_unicode);
+
+ // Note: you cannot insert any blob values this way. But you can check the API at least partly this way
+ // Extra BLOB tests are in mysqli_stmt_send_long()
+ func_mysqli_stmt_bind_result($link, $engine, "b", "BLOB", b"", 1580);
+ func_mysqli_stmt_bind_result($link, $engine, "b", "TEXT", "", 1600, $hint_str_or_unicode);
+ func_mysqli_stmt_bind_result($link, $engine, "b", "MEDIUMBLOB", b"", 1620);
+ func_mysqli_stmt_bind_result($link, $engine, "b", "MEDIUMTEXT", "", 1640, $hint_str_or_unicode);
+
+ /* Is this one related? http://bugs.php.net/bug.php?id=35759 */
+ if (($IS_MYSQLND) || (!$IS_MYSQLND && (ini_get('memory_limit') > 4294967296))) {
+ /* NOTE: the MySQL Client Library - not mysqlnd - will allocate
+ a hugge max_length(type) = 4GB bind buffer */
+ func_mysqli_stmt_bind_result($link, $engine, "b", "LONGBLOB", "", 1660);
+ func_mysqli_stmt_bind_result($link, $engine, "b", "LONGTEXT", "", 1680, $hint_str_or_unicode);
+ }
+
+ func_mysqli_stmt_bind_result($link, $engine, "s", "ENUM('a', 'b')", "a", 1700, $hint_str_or_unicode);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "ENUM('a', 'b')", NULL, 1720, $hint_str_or_unicode);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "SET('a', 'b')", "a", 1740, $hint_str_or_unicode);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "SET('a', 'b')", NULL, 1760, $hint_str_or_unicode);
+
+ if (mysqli_get_server_version($link) >= 50600)
+ func_mysqli_stmt_bind_result($link, $engine, "s", "TIME", "13:31:34.123456", 1770, "13:31:34");
+
+ /* Check that the function alias exists. It's a deprecated function,
+ but we have not announce the removal so far, therefore we need to check for it */
+ if (!is_null($tmp = @mysqli_stmt_bind_result()))
+ printf("[3000] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ $stmt = mysqli_stmt_init($link);
+ if (!mysqli_stmt_prepare($stmt, "INSERT INTO test(id, label) VALUES (1000, 'z')"))
+ printf("[3001] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = null;
+ if (false !== @mysqli_stmt_bind_result($stmt, $id))
+ printf("[3002] Bind result should not be allowed");
+
+ mysqli_stmt_close($stmt);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Warning: mysqli_stmt_bind_result(): invalid object or resource mysqli_stmt
+ in %s on line %d
+
+Warning: mysqli_stmt_bind_result(): Number of bind variables doesn't match number of fields in prepared statement in %s on line %d
+
+Warning: mysqli_stmt_bind_result(): Number of bind variables doesn't match number of fields in prepared statement in %s on line %d
+int(1)
+%s(1) "a"
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_bind_result_bit.phpt b/ext/mysqli/tests/mysqli_stmt_bind_result_bit.phpt
new file mode 100644
index 0000000..acf0d0b
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_bind_result_bit.phpt
@@ -0,0 +1,159 @@
+--TEST--
+mysqli_stmt_bind_result()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ function dec32bin($dec, $bits) {
+
+ $maxval = pow(2, $bits);
+ $bin = '';
+ for ($bitval = $maxval; $bitval >= 1; $bitval = $bitval / 2) {
+ if (($dec / $bitval) >= 1) {
+ $bin .= '1';
+ $dec -= $bitval;
+ } else {
+ $bin .= '0';
+ }
+ }
+ return $bin;
+ }
+
+ if (!$link_ins = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[001] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ if (!$link_sel = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[002] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ for ($bits = 1; $bits <= 46; $bits++) {
+
+ if (1 == $bits)
+ $max_value = 1;
+ else
+ $max_value = pow(2, $bits) - 1;
+
+ if (!mysqli_query($link_ins, "DROP TABLE IF EXISTS test")) {
+ printf("[003 - %d] [%d] %s\n", $bits, mysqli_errno($link_ins), mysqli_error($link_ins));
+ }
+
+ if (!mysqli_query($link_ins, sprintf("CREATE TABLE test(id BIGINT, bit_value BIT(%d) NOT NULL, bit_null BIT(%d) DEFAULT NULL) ENGINE = %s", $bits, $bits, $engine))) {
+ // don't bail - column type might not be supported by the server, ignore this
+ continue;
+ }
+ if (!$stmt_ins = mysqli_stmt_init($link_ins)) {
+ printf("[004 - %d] [%d] %s\n", $bits, mysqli_errno($link_ins), mysqli_error($link_ins));
+ continue;
+ }
+
+ if (!mysqli_stmt_prepare($stmt_ins, "INSERT INTO test(id, bit_value) VALUES (?, ?)")) {
+ printf("[005 - %d] [%d] %s\n", $bits, mysqli_stmt_errno($stmt_ins), mysqli_stmt_error($stmt_ins));
+ mysqli_stmt_close($stmt_ins);
+ continue;
+ }
+
+ if (!($stmt_sel = mysqli_stmt_init($link_sel))) {
+ printf("[006 - %d] [%d] %s\n", $bits, mysqli_errno($link_sel), mysqli_error($link_sel));
+ mysqli_stmt_close($stmt_ins);
+ continue;
+ }
+
+ $tests = 0;
+ $rand_max = mt_getrandmax();
+ while ($tests < 10) {
+
+ $tests++;
+ if (1 == $tests)
+ $value = 0;
+ else if (2 == $tests)
+ $value = $max_value;
+ else {
+ if ($max_value > $rand_max) {
+ $max_loops = floor($max_value/$rand_max);
+ $num_loops = mt_rand(1, $max_loops);
+ $value = 0;
+ for ($i = 0; $i < $num_loops; $i++)
+ $value += mt_rand(0, $rand_max);
+ } else {
+ $value = mt_rand(0, $max_value);
+ }
+ }
+
+ $bin = ($bits < 32) ? decbin($value) : dec32bin($value, $bits);
+ for ($i = 0; ($i < strlen($bin)) && ($bin[$i] == '0'); $i++)
+ ;
+ $bin2 = substr($bin, $i, strlen($bin));
+
+ if (!mysqli_stmt_bind_param($stmt_ins, "dd", $value, $value)) {
+ printf("[007 - %d] [%d] %s\n", $bits, mysqli_stmt_errno($stmt_ins), mysqli_stmt_error($stmt_ins));
+ mysqli_stmt_close($stmt_ins);
+ continue;
+ }
+ if (!mysqli_stmt_execute($stmt_ins)) {
+ printf("[008 - %d] [%d] %s\n", $bits, mysqli_stmt_errno($stmt_ins), mysqli_stmt_error($stmt_ins));
+ break;
+ }
+ $sql = sprintf("SELECT id, BIN(bit_value) AS _bin, bit_value, bit_value + 0 AS _bit_value0, bit_null FROM test WHERE id = %s", $value);
+ if ((!mysqli_stmt_prepare($stmt_sel, $sql)) ||
+ (!mysqli_stmt_execute($stmt_sel))) {
+ printf("[009 - %d] [%d] %s\n", $bits, mysqli_stmt_errno($stmt_sel), mysqli_stmt_error($stmt_sel));
+ break;
+ }
+
+ $row = array('id' => -1, '_bin' => - 1, 'bit_value' => -1, '_bit_value0' => -1, 'bit_null' => -1);
+ if (!mysqli_stmt_bind_result($stmt_sel, $row['id'], $row['_bin'], $row['bit_value'], $row['_bit_value0'], $row['bit_null'])) {
+ printf("[010 - %d] [%d] %s\n", $bits, mysqli_stmt_errno($stmt_sel), mysqli_stmt_error($stmt_sel));
+ break;
+ }
+
+ if (!($ret = mysqli_stmt_fetch($stmt_sel))) {
+ printf("[011 - %d] mysqli_stmt_fetch() has failed for %d bits - ret = %s/%s, [%d] %s, [%d] %s\n",
+ $bits, $bits,
+ gettype($ret), $ret,
+ mysqli_stmt_errno($stmt_sel), mysqli_stmt_error($stmt_sel),
+ mysqli_errno($link_sel), mysqli_errno($link_sel)
+ );
+ break;
+ }
+
+ if (($value != $row['id']) || (($bin != $row['_bin']) && ($bin2 != $row['_bin']))) {
+ debug_zval_dump($row);
+ printf("[012 - %d] Insert of %s in BIT(%d) column might have failed. id = %s, bin = %s (%s/%s)\n",
+ $bits, $value, $bits, $row['id'], $row['_bin'], $bin, $bin2);
+ break;
+ }
+ if ($value != $row['bit_value']) {
+ debug_zval_dump($row);
+ printf("[013 - %d] Expecting %s got %s\n", $bits, $value, $row['bit_value']);
+ break;
+ }
+
+ if (null !== $row['bit_null']) {
+ debug_zval_dump($row);
+ printf("[014 - %d] Expecting null got %s/%s\n", $bits, gettype($row['bit_value']), $row['bit_value']);
+ break;
+ }
+
+ }
+
+ mysqli_stmt_close($stmt_ins);
+ mysqli_stmt_close($stmt_sel);
+ }
+
+ mysqli_close($link_ins);
+ mysqli_close($link_sel);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_bind_result_format.phpt b/ext/mysqli/tests/mysqli_stmt_bind_result_format.phpt
new file mode 100644
index 0000000..dee5a7e
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_bind_result_format.phpt
@@ -0,0 +1,337 @@
+--TEST--
+Playing with SELECT FORMAT(...) AS _format - see also bugs.php.net/42378
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--INI--
+memory_limit=83886080
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ function create_table($link, $column, $min, $max, $engine, $offset) {
+
+ if (!mysqli_query($link, 'DROP TABLE IF EXISTS test')) {
+ printf("[%03d] Cannot drop table test, [%d] %s\n",
+ $offset,
+ mysqli_errno($link), mysqli_error($link));
+ return array();
+ }
+
+ $sql = sprintf("CREATE TABLE test(id INT AUTO_INCREMENT PRIMARY KEY, col1 %s) ENGINE=%s",
+ $column, $engine);
+ if (!mysqli_query($link, $sql)) {
+ printf("[%03d] Cannot create table test, [%d] %s\n",
+ $offset + 1,
+ mysqli_errno($link), mysqli_error($link));
+ return array();
+ }
+
+ $values = array();
+ for ($i = 1; $i <= 100; $i++) {
+ $col1 = mt_rand($min, $max);
+ $values[$i] = $col1;
+ $sql = sprintf("INSERT INTO test(id, col1) VALUES (%d, %f)",
+ $i, $col1);
+ if (!mysqli_query($link, $sql)) {
+ printf("[%03d] Cannot insert data, [%d] %s\n",
+ $offset + 2,
+ mysqli_errno($link), mysqli_error($link));
+ return array();
+ }
+ }
+
+ return $values;
+ }
+
+ function test_format($link, $format, $from, $order_by, $expected, $offset) {
+
+ if (!$stmt = mysqli_stmt_init($link)) {
+ printf("[%03d] Cannot create PS, [%d] %s\n",
+ $offset,
+ mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ if ($order_by)
+ $sql = sprintf('SELECT %s AS _format FROM %s ORDER BY %s', $format, $from, $order_by);
+ else
+ $sql = sprintf('SELECT %s AS _format FROM %s', $format, $from);
+
+ if (!mysqli_stmt_prepare($stmt, $sql)) {
+ printf("[%03d] Cannot prepare PS, [%d] %s\n",
+ $offset + 1,
+ mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ return false;
+ }
+
+ if (!mysqli_stmt_execute($stmt)) {
+ printf("[%03d] Cannot execute PS, [%d] %s\n",
+ $offset + 2,
+ mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ return false;
+ }
+
+ if (!mysqli_stmt_store_result($stmt)) {
+ printf("[%03d] Cannot store result set, [%d] %s\n",
+ $offset + 3,
+ mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ return false;
+ }
+
+ if (!is_array($expected)) {
+
+ $result = null;
+ if (!mysqli_stmt_bind_result($stmt, $result)) {
+ printf("[%03d] Cannot bind result, [%d] %s\n",
+ $offset + 4,
+ mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ return false;
+ }
+
+ if (!mysqli_stmt_fetch($stmt)) {
+ printf("[%03d] Cannot fetch result,, [%d] %s\n",
+ $offset + 5,
+ mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ return false;
+ }
+
+ if ($result !== $expected) {
+ printf("[%03d] Expecting %s/%s got %s/%s with %s - %s.\n",
+ $offset + 6,
+ gettype($expected), $expected,
+ gettype($result), $result,
+ $format, $sql);
+ }
+
+ } else {
+
+ $order_by_col = $result = null;
+ if (!mysqli_stmt_bind_result($stmt, $order_by_col, $result)) {
+ printf("[%03d] Cannot bind result, [%d] %s\n",
+ $offset + 7,
+ mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ return false;
+ }
+
+ reset($expected);
+ while ((list($k, $v) = each($expected)) && mysqli_stmt_fetch($stmt)) {
+ if ($result !== $v) {
+ printf("[%03d] Row %d - expecting %s/%s got %s/%s [%s] with %s - %s.\n",
+ $offset + 8,
+ $k,
+ gettype($v), $v,
+ gettype($result), $result,
+ $order_by_col,
+ $format, $sql);
+ }
+ }
+
+ }
+
+ mysqli_stmt_free_result($stmt);
+ mysqli_stmt_close($stmt);
+
+ return true;
+ }
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[001] Cannot connect - [%d] %s\n",
+ mysqli_connect_errno(),
+ mysqli_connect_error());
+
+ /* select from dual - pseudo table */
+ test_format($link, 'FORMAT(1.01, 0)', 'DUAL', null, '1', 10);
+ test_format($link, 'FORMAT(1.23, 1)', 'DUAL', null, '1.2', 20);
+ test_format($link, 'FORMAT(1.23, 2)', 'DUAL', null, '1.23', 30);
+ test_format($link, 'FORMAT(1234.567, 3)', 'DUAL', null, '1,234.567', 40);
+ /* no typo! */
+ test_format($link, 'FORMAT(1234.567, 4)', 'DUAL', null, '1,234.5670', 50);
+
+ mysqli_close($link);
+ require_once('table.inc');
+
+ /* select from existing table */
+ test_format($link, 'FORMAT(id, 0)', 'test', null, '1', 60);
+ test_format($link, 'FORMAT(id + 0.1, 1)', 'test', null, '1.1', 70);
+ test_format($link, 'FORMAT(id + 0.01, 2)', 'test', null, '1.01', 80);
+
+ /* create new table and select from it */
+ $expected = create_table($link, 'FLOAT', -10000, 10000, $engine, 90);
+ foreach ($expected as $k => $v)
+ $expected[$k] = number_format(round($v), 0, '.', ',');
+ test_format($link, 'id AS order_by_col, FORMAT(col1, 0)', 'test', 'id', $expected, 100);
+
+ $expected = create_table($link, 'FLOAT UNSIGNED', 0, 10000, $engine, 110);
+ foreach ($expected as $k => $v)
+ $expected[$k] = number_format(round($v), 0, '.', ',');
+ test_format($link, 'id AS order_by_col, FORMAT(col1, 0)', 'test', 'id', $expected, 120);
+
+ $expected = create_table($link, 'TINYINT', -128, 127, $engine, 130);
+ foreach ($expected as $k => $v)
+ $expected[$k] = number_format(round($v), 0, '.', ',');
+ test_format($link, 'id AS order_by_col, FORMAT(col1, 0)', 'test', 'id', $expected, 140);
+
+ $expected = create_table($link, 'SMALLINT UNSIGNED', 0, 65535, $engine, 150);
+ foreach ($expected as $k => $v)
+ $expected[$k] = number_format(round($v), 0, '.', ',');
+ test_format($link, 'id AS order_by_col, FORMAT(col1, 0)', 'test', 'id', $expected, 160);
+
+ $expected = create_table($link, 'MEDIUMINT', 0, 8388607, $engine, 170);
+ foreach ($expected as $k => $v)
+ $expected[$k] = number_format(round($v), 0, '.', ',');
+ test_format($link, 'id AS order_by_col, FORMAT(col1, 0)', 'test', 'id', $expected, 180);
+
+ $expected = create_table($link, 'INT UNSIGNED', 0, 1000, $engine, 190);
+ foreach ($expected as $k => $v)
+ $expected[$k] = number_format(round($v), 0, '.', ',');
+ test_format($link, 'id AS order_by_col, FORMAT(col1, 0)', 'test', 'id', $expected, 200);
+
+ $expected = create_table($link, 'BIGINT', -1000, 1000, $engine, 210);
+ foreach ($expected as $k => $v)
+ $expected[$k] = number_format(round($v), 0, '.', ',');
+ test_format($link, 'id AS order_by_col, FORMAT(col1, 0)', 'test', 'id', $expected, 220);
+
+ $expected = create_table($link, 'DECIMAL(5,0)', -1000, 1000, $engine, 230);
+ foreach ($expected as $k => $v)
+ $expected[$k] = number_format(round($v), 0, '.', ',');
+ test_format($link, 'id AS order_by_col, FORMAT(col1, 0)', 'test', 'id', $expected, 240);
+
+ // http://bugs.php.net/bug.php?id=42378
+ if (!mysqli_query($link, "DROP TABLE IF EXISTS test")) {
+ printf("[300] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ if (mysqli_query($link, "CREATE TABLE `test` (
+ `targetport` int(11) NOT NULL default '0',
+ `sources` double(17,4) default NULL,
+ `current_sources` double(17,0) default NULL,
+ `reports` double(17,4) default NULL,
+ `current_reports` double(17,0) default NULL,
+ `targets` double(17,4) default NULL,
+ `current_targets` double(17,0) default NULL,
+ `maxsources` int(11) default NULL,
+ `maxtargets` int(11) default NULL,
+ `maxreports` int(11) default NULL,
+ `trend` float default NULL,
+ PRIMARY KEY (`targetport`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1")) {
+
+ do {
+ $values = array();
+ for ($i = 0; $i < 200; $i++) {
+ $current_targets = mt_rand(-100000, 100000) / 10;
+ do {
+ $trend = (mt_rand(0, 3) > 1) ? (mt_rand(-10000, 10000) / 100) : 'NULL';
+ } while (isset($values[$trend]));
+
+ $sql = sprintf('INSERT INTO test(targetport, current_targets, maxreports, trend) VALUES (%d, %f, %s, %s)',
+ $i,
+ $current_targets,
+ (mt_rand(0, 1) > 0) ? mt_rand(0, 1000) : 'NULL',
+ $trend);
+ if (!mysqli_query($link, $sql)) {
+ printf("[301] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ break 2;
+ }
+ if ($current_targets > 0 && $trend != 'NULL')
+ $values[$trend] = $i;
+ }
+ krsort($values);
+
+ if (!$stmt = mysqli_stmt_init($link)) {
+ printf("[302] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ break;
+ }
+
+ if (!mysqli_stmt_prepare($stmt, 'SELECT trend, targetport, FORMAT(trend, 2) FROM test WHERE current_targets > 0 AND trend IS NOT NULL ORDER BY trend DESC LIMIT 100')) {
+ printf("[303] [%d] %s\n", mysqli_stmt_errno($link), mysqli_stmt_error($link));
+ break;
+ }
+
+ if (!mysqli_stmt_execute($stmt)) {
+ printf("[304] [%d] %s\n", mysqli_stmt_errno($link), mysqli_stmt_error($link));
+ break;
+ }
+
+ if (!mysqli_stmt_store_result($stmt)) {
+ printf("[305] [%d] %s\n", mysqli_stmt_errno($link), mysqli_stmt_error($link));
+ break;
+ }
+
+ $trend = $targetport = $format = null;
+ if (!mysqli_stmt_bind_result($stmt, $trend, $targetport, $format)) {
+
+ printf("[305] [%d] %s\n", mysqli_stmt_errno($link), mysqli_stmt_error($link));
+ break;
+ }
+
+ reset($values);
+ while (mysqli_stmt_fetch($stmt)) {
+ list($exp_trend, $exp_targetport) = each($values);
+ if ($targetport != $exp_targetport) {
+ printf("[306] Values fetched from MySQL seem to be wrong, check manually\n");
+ printf("%s/%s - %s/%s - '%s'\n", $trend, $exp_trend, $targetport, $exp_targetport, $format);
+ }
+ }
+ mysqli_stmt_free_result($stmt);
+ mysqli_stmt_close($stmt);
+
+ // same but OO interface
+ if (!$stmt = mysqli_stmt_init($link)) {
+ printf("[307] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ break;
+ }
+
+ if (!$stmt->prepare('SELECT trend, targetport, FORMAT(trend, 2) FROM test WHERE current_targets > 0 AND trend IS NOT NULL ORDER BY trend DESC LIMIT 100')) {
+ printf("[308] [%d] %s\n", mysqli_stmt_errno($link), mysqli_stmt_error($link));
+ break;
+ }
+
+ if (!$stmt->execute()) {
+ printf("[309] [%d] %s\n", mysqli_stmt_errno($link), mysqli_stmt_error($link));
+ break;
+ }
+
+ if (!$stmt->store_result()) {
+ printf("[310] [%d] %s\n", mysqli_stmt_errno($link), mysqli_stmt_error($link));
+ break;
+ }
+
+ $trend = $targetport = $format = null;
+ if (!$stmt->bind_result($trend, $targetport, $format)) {
+
+ printf("[311] [%d] %s\n", mysqli_stmt_errno($link), mysqli_stmt_error($link));
+ break;
+ }
+
+ reset($values);
+ while ($stmt->fetch()) {
+ list($exp_trend, $exp_targetport) = each($values);
+ if ($targetport != $exp_targetport) {
+ printf("[312] Values fetched from MySQL seem to be wrong, check manually\n");
+ printf("%s/%s - %s/%s - '%s'\n", $trend, $exp_trend, $targetport, $exp_targetport, $format);
+ }
+ }
+ $stmt->free_result();
+ $stmt->close();
+
+ } while (false);
+
+ } else {
+ var_dump(mysqli_error($link));
+ }
+
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_bind_result_references.phpt b/ext/mysqli/tests/mysqli_stmt_bind_result_references.phpt
new file mode 100644
index 0000000..ee659d4
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_bind_result_references.phpt
@@ -0,0 +1,314 @@
+--TEST--
+mysqli_stmt_bind_result() - playing with references
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require('table.inc');
+
+ $stmt = mysqli_stmt_init($link);
+ if (!mysqli_stmt_prepare($stmt, "SELECT id, label FROM test ORDER BY id LIMIT 1"))
+ printf("[001] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_prepare($stmt, "SELECT id, label FROM test ORDER BY id LIMIT 1"))
+ printf("[001] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+
+ print "plain vanilla...\n";
+ unset($id); unset($label);
+ $id = $label = null;
+ if (true !== ($tmp = mysqli_stmt_bind_result($stmt, $id, $label)))
+ printf("[002] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_execute($stmt) || !mysqli_stmt_fetch($stmt) || mysqli_stmt_fetch($stmt))
+ printf("[003] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ var_dump($id);
+ var_dump($label);
+
+
+ print "reference, one level...\n";
+ unset($id); unset($id_ref); unset($label); unset($label_ref);
+ $id = null;
+ $id_ref = &$id;
+ $label = null;
+ $label_ref = &$label;
+
+ if (true !== ($tmp = mysqli_stmt_bind_result($stmt, $id_ref, $label_ref)))
+ printf("[004] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_execute($stmt) || !mysqli_stmt_fetch($stmt) || mysqli_stmt_fetch($stmt))
+ printf("[005] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ var_dump($id_ref);
+ var_dump($id);
+ var_dump($label_ref);
+ var_dump($label);
+
+
+ print "reference, two levels...\n";
+ unset($id); unset($id_ref); unset($id_ref_ref); unset($label); unset($label_ref); unset($label_ref_ref);
+ $id = null;
+ $id_ref = &$id;
+ $id_ref_ref = &$id_ref;
+ $label = null;
+ $label_ref = &$label;
+ $label_ref_ref = &$label_ref;
+
+ if (true !== ($tmp = mysqli_stmt_bind_result($stmt, $id_ref_ref, $label_ref_ref)))
+ printf("[006] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_execute($stmt) || !mysqli_stmt_fetch($stmt) || mysqli_stmt_fetch($stmt))
+ printf("[007] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ var_dump($id_ref_ref);
+ var_dump($id_ref);
+ var_dump($id);
+ var_dump($label_ref_ref);
+ var_dump($label_ref);
+ var_dump($label);
+
+ print "reference, \$GLOBALS...\n";
+ unset($id); unset($id_ref); unset($label); unset($label_ref);
+ $id = 100;
+ $id_ref = &$GLOBALS['id'];
+ $label = null;
+ $label_ref = &$GLOBALS['label'];
+
+ if (true !== ($tmp = mysqli_stmt_bind_result($stmt, $id_ref, $label_ref)))
+ printf("[008] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_execute($stmt) || !mysqli_stmt_fetch($stmt) || mysqli_stmt_fetch($stmt))
+ printf("[009] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ var_dump($id_ref);
+ var_dump($id);
+ var_dump($label_ref);
+ var_dump($label);
+
+ print "reference, same target...\n";
+ $id = null;
+ $label = &$id;
+
+ if (true !== ($tmp = mysqli_stmt_bind_result($stmt, $id, $label)))
+ printf("[010] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_execute($stmt) || !mysqli_stmt_fetch($stmt) || mysqli_stmt_fetch($stmt))
+ printf("[011] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ var_dump($id);
+ var_dump($label);
+
+ print "reference, simple object...\n";
+ unset($obj);
+ $obj = new stdClass();
+ $obj->id = null;
+ $obj->label = null;
+
+ if (true !== ($tmp = mysqli_stmt_bind_result($stmt, $obj->id, $obj->label)))
+ printf("[012] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_execute($stmt) || !mysqli_stmt_fetch($stmt) || mysqli_stmt_fetch($stmt))
+ printf("[013] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ var_dump($obj->id);
+ var_dump($obj->label);
+
+
+ print "reference, simple object w reference...\n";
+ unset($id); unset($label); unset($obj);
+ $obj = new stdClass();
+ $obj->id = null;
+ $obj->label = null;
+ $id = &$obj->id;
+ $label = &$obj->label;
+
+ if (true !== ($tmp = mysqli_stmt_bind_result($stmt, $id, $label)))
+ printf("[012] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_execute($stmt) || !mysqli_stmt_fetch($stmt) || mysqli_stmt_fetch($stmt))
+ printf("[013] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ var_dump($obj->id);
+ var_dump($obj->label);
+
+ print "reference, simple object w reference, change after bind...\n";
+ unset($id); unset($label); unset($obj);
+ $obj = new stdClass();
+ $obj->id = null;
+ $obj->label = null;
+ $id = &$obj->id;
+ $label = &$obj->label;
+
+ if (true !== ($tmp = mysqli_stmt_bind_result($stmt, $id, $label)))
+ printf("[012] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ $label = &$obj->id;
+ $id = null;
+
+ if (!mysqli_stmt_execute($stmt) || !mysqli_stmt_fetch($stmt) || mysqli_stmt_fetch($stmt))
+ printf("[013] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ var_dump($obj->id);
+ var_dump($id);
+ var_dump($obj->label);
+ var_dump($label);
+
+ print "reference, one level, change after bind...\n";
+ unset($id); unset($label); unset($id_ref); unset($label_ref);
+ $id = null;
+ $id_ref = &$id;
+ $label = null;
+ $label_ref = &$label;
+
+ if (true !== ($tmp = mysqli_stmt_bind_result($stmt, $id_ref, $label_ref)))
+ printf("[014] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ $id_ref = 1;
+ $label_ref = 1;
+
+ if (!mysqli_stmt_execute($stmt) || !mysqli_stmt_fetch($stmt) || mysqli_stmt_fetch($stmt))
+ printf("[015] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ var_dump($id_ref);
+ var_dump($id);
+ var_dump($label_ref);
+ var_dump($label);
+
+ print "reference, circle...\n";
+ unset($id); unset($label_a); unset($label_b);
+ $id = null;
+ $label_a = &$label_b;
+ $label_b = &$label_a;
+
+ if (true !== ($tmp = mysqli_stmt_bind_result($stmt, $id, $label_a)))
+ printf("[016] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+ if (!mysqli_stmt_execute($stmt) || !mysqli_stmt_fetch($stmt) || mysqli_stmt_fetch($stmt))
+ printf("[017] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ var_dump($id);
+ var_dump($label_a);
+ var_dump($label_b);
+
+ print "reference, object, forward declaration...\n";
+ unset($bar); unset($id); unset($label_ref);
+ class foo {
+ public $foo;
+ public function foo() {
+ $this->foo = &$this->bar;
+ }
+ }
+ class bar extends foo {
+ public $bar = null;
+ }
+ $bar = new bar();
+ $id = null;
+ $label_ref = &$bar->bar;
+
+ if (true !== ($tmp = mysqli_stmt_bind_result($stmt, $id, $label_ref)))
+ printf("[018] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+ if (!mysqli_stmt_execute($stmt) || !mysqli_stmt_fetch($stmt) || mysqli_stmt_fetch($stmt))
+ printf("[019] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ var_dump($id);
+ var_dump($bar);
+ var_dump($label_ref);
+
+ print "references, object, private...\n";
+ unset($bar); unset($id); unset($label);
+ class mega_bar extends bar {
+ private $id;
+ public $id_ref;
+ public function mega_bar() {
+ $this->foo();
+ $this->id_ref = &$this->id;
+ }
+ }
+ $bar = new mega_bar();
+ $id = &$bar->id_ref;
+ $label = &$bar->foo;
+
+ if (true !== ($tmp = mysqli_stmt_bind_result($stmt, $id, $label)))
+ printf("[020] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+ if (!mysqli_stmt_execute($stmt) || !mysqli_stmt_fetch($stmt) || mysqli_stmt_fetch($stmt))
+ printf("[021] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ var_dump($id);
+ var_dump($label);
+ var_dump($bar);
+
+ mysqli_stmt_close($stmt);
+ mysqli_close($link);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+plain vanilla...
+int(1)
+%unicode|string%(1) "a"
+reference, one level...
+int(1)
+int(1)
+%unicode|string%(1) "a"
+%unicode|string%(1) "a"
+reference, two levels...
+int(1)
+int(1)
+int(1)
+%unicode|string%(1) "a"
+%unicode|string%(1) "a"
+%unicode|string%(1) "a"
+reference, $GLOBALS...
+int(1)
+int(1)
+%unicode|string%(1) "a"
+%unicode|string%(1) "a"
+reference, same target...
+%unicode|string%(1) "a"
+%unicode|string%(1) "a"
+reference, simple object...
+int(1)
+%unicode|string%(1) "a"
+reference, simple object w reference...
+int(1)
+%unicode|string%(1) "a"
+reference, simple object w reference, change after bind...
+int(1)
+int(1)
+%unicode|string%(1) "a"
+int(1)
+reference, one level, change after bind...
+int(1)
+int(1)
+%unicode|string%(1) "a"
+%unicode|string%(1) "a"
+reference, circle...
+int(1)
+%unicode|string%(1) "a"
+%unicode|string%(1) "a"
+reference, object, forward declaration...
+int(1)
+object(bar)#%d (2) {
+ [%u|b%"bar"]=>
+ &%unicode|string%(1) "a"
+ [%u|b%"foo"]=>
+ &%unicode|string%(1) "a"
+}
+%unicode|string%(1) "a"
+references, object, private...
+int(1)
+%unicode|string%(1) "a"
+object(mega_bar)#5 (4) {
+ [%s]=>
+ &int(1)
+ [%u|b%"id_ref"]=>
+ &int(1)
+ [%u|b%"bar"]=>
+ &%unicode|string%(1) "a"
+ [%u|b%"foo"]=>
+ &%unicode|string%(1) "a"
+}
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_bind_result_zerofill.phpt b/ext/mysqli/tests/mysqli_stmt_bind_result_zerofill.phpt
new file mode 100644
index 0000000..5650853
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_bind_result_zerofill.phpt
@@ -0,0 +1,97 @@
+--TEST--
+mysqli_stmt_bind_result() - ZEROFILL
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once('connect.inc');
+ require_once('table.inc');
+
+ function zerofill($offset, $link, $datatype, $insert = 1) {
+
+ mysqli_query($link, 'ALTER TABLE test DROP zero');
+ $sql = sprintf('ALTER TABLE test ADD zero %s UNSIGNED ZEROFILL', $datatype);
+ if (!mysqli_query($link, $sql)) {
+ // no worries - server might not support it
+ return true;
+ }
+
+ if (!mysqli_query($link, sprintf('UPDATE test SET zero = %s', $insert))) {
+ printf("[%03d] UPDATE failed, [%d] %s\n",
+ $offset, mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ if (!($stmt = mysqli_prepare($link, 'SELECT zero FROM test LIMIT 1'))) {
+ printf("[%03d] SELECT failed, [%d] %s\n",
+ $offset, mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ $result = null;
+ if (!mysqli_stmt_bind_result($stmt, $result)) {
+ printf("[%03d] Bind failed, [%d] %s\n",
+ mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ return false;
+ }
+
+ if (!mysqli_stmt_execute($stmt) || !mysqli_stmt_fetch($stmt)) {
+ printf("[%03d] Execute or fetch failed, [%d] %s\n",
+ mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ return false;
+ }
+
+ $res = mysqli_stmt_result_metadata($stmt);
+ $meta = mysqli_fetch_fields($res);
+ mysqli_stmt_free_result($stmt);
+
+ $meta = $meta[0];
+ $length = $meta->length;
+ if ($length > strlen($insert)) {
+
+ $expected = str_repeat('0', $length - strlen($insert));
+ $expected .= $insert;
+ if ($expected !== $result) {
+ printf("[%03d] Expecting '%s' got '%s'\n", $offset, $expected, $result);
+ return false;
+ }
+
+ } else if ($length <= 1) {
+ printf("[%03d] Length reported is too small to run test\n", $offset);
+ return false;
+ }
+
+
+ return true;
+ }
+
+ /*
+ We map those to PHP numeric types -
+ no padding/filling done. Neither with libmysql nor with mysqlnd.
+ zerofill(2, $link, 'TINYINT');
+ zerofill(3, $link, 'SMALLINT');
+ zerofill(4, $link, 'MEDIUMINT');
+ zerofill(5, $link, 'INT');
+ zerofill(6, $link, 'INTEGER');
+ zerofill(7, $link, 'BIGINT');
+ zerofill(8, $link, 'FLOAT');
+ zerofill(9, $link, 'DOUBLE');
+ zerofill(10, $link, 'DOUBLE PRECISION');
+ */
+ zerofill(11, $link, 'DECIMAL');
+ zerofill(12, $link, 'DEC');
+
+ mysqli_close($link);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_close.phpt b/ext/mysqli/tests/mysqli_stmt_close.phpt
new file mode 100644
index 0000000..64e76e5
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_close.phpt
@@ -0,0 +1,91 @@
+--TEST--
+mysqli_stmt_close()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_stmt_close()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_close($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ // Yes, amazing, eh? AFAIK a work around of a constructor bug...
+ if (!is_null($tmp = mysqli_stmt_close($stmt)))
+ printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_prepare($stmt, "SELECT id, label FROM test"))
+ printf("[005] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (true !== ($tmp = mysqli_stmt_close($stmt)))
+ printf("[006] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = mysqli_stmt_close($stmt)))
+ printf("[007] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[008] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_stmt_prepare($stmt, "INSERT INTO test(id, label) VALUES (?, ?)"))
+ printf("[009] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = $label = null;
+ if (!mysqli_stmt_bind_param($stmt, "is", $id, $label))
+ printf("[010] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = 100; $label = 'z';
+ if (!mysqli_stmt_execute($stmt))
+ printf("[011] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ mysqli_kill($link, mysqli_thread_id($link));
+
+ if (true !== ($tmp = mysqli_stmt_close($stmt)))
+ printf("[012] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_close($link);
+
+ require('table.inc');
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[013] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_stmt_prepare($stmt, "SELECT id, label FROM test"))
+ printf("[014] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = $label = null;
+ if (!mysqli_stmt_bind_result($stmt, $id, $label))
+ printf("[015] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_execute($stmt) || !mysqli_stmt_fetch($stmt))
+ printf("[016] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ mysqli_kill($link, mysqli_thread_id($link));
+
+ if (true !== ($tmp = mysqli_stmt_close($stmt)))
+ printf("[017] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Warning: mysqli_stmt_close(): invalid object or resource mysqli_stmt
+ in %s on line %d
+
+Warning: mysqli_stmt_close(): Couldn't fetch mysqli_stmt in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_data_seek.phpt b/ext/mysqli/tests/mysqli_stmt_data_seek.phpt
new file mode 100644
index 0000000..a1cebea
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_data_seek.phpt
@@ -0,0 +1,99 @@
+--TEST--
+mysqli_stmt_data_seek()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_stmt_data_seek()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_data_seek($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!is_null($tmp = mysqli_stmt_data_seek($stmt, 1)))
+ printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_prepare($stmt, "SELECT id FROM test ORDER BY id"))
+ printf("[005] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (true !== ($tmp = mysqli_stmt_execute($stmt)))
+ printf("[006] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+
+ $id = null;
+ if (!mysqli_stmt_bind_result($stmt, $id))
+ printf("[007] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_store_result($stmt))
+ printf("[008] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!is_null($tmp = mysqli_stmt_data_seek($stmt, 2)))
+ printf("[009] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_fetch($stmt))
+ printf("[010] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ var_dump($id);
+
+ if (!is_null($tmp = mysqli_stmt_data_seek($stmt, 0)))
+ printf("[011] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_fetch($stmt))
+ printf("[012] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ var_dump($id);
+
+ if (!is_null($tmp = mysqli_stmt_data_seek($stmt, mysqli_stmt_num_rows($stmt) + 100)))
+ printf("[013] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (mysqli_stmt_fetch($stmt))
+ printf("[014] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ var_dump($id);
+
+ if (false !== ($tmp = mysqli_stmt_data_seek($stmt, -1)))
+ printf("[015] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (mysqli_stmt_fetch($stmt))
+ printf("[016] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ var_dump($id);
+
+ mysqli_stmt_close($stmt);
+
+ if (NULL !== ($tmp = mysqli_stmt_data_seek($stmt, 0)))
+ printf("[017] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Warning: mysqli_stmt_data_seek(): invalid object or resource mysqli_stmt
+ in %s on line %d
+int(3)
+int(1)
+int(1)
+
+Warning: mysqli_stmt_data_seek(): Offset must be positive in %s on line %d
+int(1)
+
+Warning: mysqli_stmt_data_seek(): Couldn't fetch mysqli_stmt in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_datatype_change.phpt b/ext/mysqli/tests/mysqli_stmt_datatype_change.phpt
new file mode 100644
index 0000000..b23f94d
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_datatype_change.phpt
@@ -0,0 +1,94 @@
+--TEST--
+Playing with datatype change between prepare and execute
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+ if (!$c1 = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ printf("Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+ exit(1);
+ }
+ if (!$c2 = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ printf("Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+ exit(1);
+ }
+
+ $c1->query("use $db");
+ $c2->query("use $db");
+ $c1->query("drop table if exists type_change");
+ $c1->query("create table type_change(a int, b char(10)) ENGINE = " . $engine);
+ $c1->query("insert into type_change values (1, 'one'), (2, 'two')");
+ $s1 = $c1->prepare("select a from type_change order by a");
+ var_dump($s1->execute(), $s1->bind_result($col1));
+ echo "---- Row 1\n";
+ var_dump($s1->fetch());
+ var_dump($col1);
+ echo "---- Row 2\n";
+ var_dump($s1->fetch());
+ var_dump($col1);
+ echo "---- Row 3\n";
+ var_dump($s1->fetch());
+ echo "----\n";
+
+ echo "ALTER\n";
+ var_dump($c2->query("alter table type_change drop a"));
+ var_dump($s1->execute());
+ var_dump($c1->error);
+
+ echo "---- Row 1\n";
+ var_dump($s1->fetch());
+ var_dump($col1);
+ echo "---- Row 2\n";
+ var_dump($s1->fetch());
+ var_dump($col1);
+ echo "---- Row 3\n";
+ var_dump($s1->fetch());
+ echo "----\n";
+
+ echo "done!";
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS type_change"))
+ printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+mysqli_close($link);
+?>
+
+--EXPECTF--
+bool(true)
+bool(true)
+---- Row 1
+bool(true)
+int(1)
+---- Row 2
+bool(true)
+int(2)
+---- Row 3
+NULL
+----
+ALTER
+bool(true)
+bool(false)
+%unicode|string%(34) "Unknown column 'a' in 'field list'"
+---- Row 1
+bool(false)
+int(2)
+---- Row 2
+bool(false)
+int(2)
+---- Row 3
+bool(false)
+----
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_errno.phpt b/ext/mysqli/tests/mysqli_stmt_errno.phpt
new file mode 100644
index 0000000..070f251
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_errno.phpt
@@ -0,0 +1,68 @@
+--TEST--
+mysqli_stmt_errno()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_stmt_errno()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_errno($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ // properly initialized?
+ if (0 !== ($tmp = mysqli_stmt_errno($stmt)))
+ printf("[004] Expecting int/0, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (mysqli_stmt_prepare($stmt, "SELECT i_do_not_exist_believe_me FROM test ORDER BY id"))
+ printf("[005] Statement should have failed!\n");
+
+ // set after error server?
+ if (0 === ($tmp = mysqli_stmt_errno($stmt)))
+ printf("[006] Expecting int/any non zero, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_prepare($stmt, "SELECT id FROM test ORDER BY id"))
+ printf("[007] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ // reset after error & success
+ if (0 != ($tmp = mysqli_stmt_errno($stmt)))
+ printf("[008] Expecting zero, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_kill($link, mysqli_thread_id($link));
+
+ if (true === ($tmp = mysqli_stmt_execute($stmt)))
+ printf("[009] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ // set after client error
+ if (0 === ($tmp = mysqli_stmt_errno($stmt)))
+ printf("[010] Execting int/any non zero, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_stmt_close($stmt);
+
+ if (NULL !== ($tmp = mysqli_stmt_errno($stmt)))
+ printf("[011] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Warning: mysqli_stmt_errno(): Couldn't fetch mysqli_stmt in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_error.phpt b/ext/mysqli/tests/mysqli_stmt_error.phpt
new file mode 100644
index 0000000..e18aa07
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_error.phpt
@@ -0,0 +1,68 @@
+--TEST--
+mysqli_stmt_error()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_stmt_error()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_error($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ // properly initialized?
+ if ('' !== ($tmp = mysqli_stmt_error($stmt)))
+ printf("[004] Expecting int/0, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (mysqli_stmt_prepare($stmt, "SELECT i_do_not_exist_believe_me FROM test ORDER BY id"))
+ printf("[005] Statement should have failed!\n");
+
+ // set after error server?
+ if ('' === ($tmp = mysqli_stmt_error($stmt)))
+ printf("[006] Expecting string/any non empty, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_prepare($stmt, "SELECT id FROM test ORDER BY id"))
+ printf("[007] [%d] %s\n", mysqli_stmt_error($stmt), mysqli_stmt_error($stmt));
+
+ // reset after error & success
+ if ('' !== ($tmp = mysqli_stmt_error($stmt)))
+ printf("[008] Expecting empty string, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_kill($link, mysqli_thread_id($link));
+
+ if (true === ($tmp = mysqli_stmt_execute($stmt)))
+ printf("[009] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ // set after client error
+ if ('' === ($tmp = mysqli_stmt_error($stmt)))
+ printf("[010] Execting string/any non empty, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_stmt_close($stmt);
+
+ if (NULL !== ($tmp = mysqli_stmt_error($stmt)))
+ printf("[011] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Warning: mysqli_stmt_error(): Couldn't fetch mysqli_stmt in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_execute.phpt b/ext/mysqli/tests/mysqli_stmt_execute.phpt
new file mode 100644
index 0000000..85ae80c
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_execute.phpt
@@ -0,0 +1,150 @@
+--TEST--
+mysqli_stmt_execute()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ die(sprintf('skip Cannot connect to MySQL, [%d] %s.', mysqli_connect_errno(), mysqli_connect_error()));
+}
+if (mysqli_get_server_version($link) <= 40100) {
+ die(sprintf('skip Needs MySQL 4.1+, found version %d.', mysqli_get_server_version($link)));
+}
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_stmt_execute()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_execute($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ // stmt object status test
+ if (NULL !== ($tmp = mysqli_stmt_execute($stmt)))
+ printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (mysqli_stmt_prepare($stmt, "SELECT i_do_not_exist_believe_me FROM test ORDER BY id"))
+ printf("[005] Statement should have failed!\n");
+
+ // stmt object status test
+ if (NULL !== ($tmp = mysqli_stmt_execute($stmt)))
+ printf("[006] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_prepare($stmt, "SELECT id FROM test ORDER BY id LIMIT 1"))
+ printf("[007] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (true !== ($tmp = mysqli_stmt_execute($stmt)))
+ printf("[008] Expecting boolean/true, got %s/%s. [%d] %s\n",
+ gettype($tmp), $tmp, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_prepare($stmt, "INSERT INTO test(id, label) VALUES (?, ?)"))
+ printf("[009] [%d] %s\n", mysqli_stmt_execute($stmt), mysqli_stmt_execute($stmt));
+
+ // no input variables bound
+ if (false !== ($tmp = mysqli_stmt_execute($stmt)))
+ printf("[010] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ $id = 100;
+ $label = "z";
+ if (!mysqli_stmt_bind_param($stmt, "is", $id, $label))
+ printf("[011] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (true !== ($tmp = mysqli_stmt_execute($stmt)))
+ printf("[012] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ // calling reset between executions
+ mysqli_stmt_close($stmt);
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[013] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_stmt_prepare($stmt, "SELECT id FROM test ORDER BY id LIMIT ?"))
+ printf("[014] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $limit = 1;
+ if (!mysqli_stmt_bind_param($stmt, "i", $limit))
+ printf("[015] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (true !== ($tmp = mysqli_stmt_execute($stmt)))
+ printf("[016] Expecting boolean/true, got %s/%s. [%d] %s\n",
+ gettype($tmp), $tmp, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = null;
+ if (!mysqli_stmt_bind_result($stmt, $id) || !mysqli_stmt_fetch($stmt))
+ printf("[017] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if ($id !== 1)
+ printf("[018] Expecting int/1 got %s/%s\n", gettype($id), $id);
+
+ if (true !== ($tmp = mysqli_stmt_reset($stmt)))
+ printf("[019] Expecting boolean/true, got %s/%s. [%d] %s\n",
+ gettype($tmp), $tmp, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (true !== ($tmp = mysqli_stmt_execute($stmt)))
+ printf("[020] Expecting boolean/true after reset to prepare status, got %s/%s. [%d] %s\n",
+ gettype($tmp), $tmp, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = null;
+ if (!mysqli_stmt_fetch($stmt))
+ printf("[021] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if ($id !== 1)
+ printf("[022] Expecting int/1 got %s/%s\n", gettype($id), $id);
+
+ mysqli_stmt_close($stmt);
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[023] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_stmt_prepare($stmt, "SELECT id FROM test ORDER BY id LIMIT 1"))
+ printf("[024] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (true !== ($tmp = mysqli_stmt_execute($stmt)))
+ printf("[025] Expecting boolean/true, got %s/%s. [%d] %s\n",
+ gettype($tmp), $tmp, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (true !== ($tmp = mysqli_stmt_reset($stmt)))
+ printf("[026] Expecting boolean/true, got %s/%s. [%d] %s\n",
+ gettype($tmp), $tmp, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ var_dump(mysqli_stmt_execute($stmt));
+ var_dump(mysqli_stmt_fetch($stmt));
+
+ mysqli_kill($link, mysqli_thread_id($link));
+
+ if (false !== ($tmp = mysqli_stmt_execute($stmt)))
+ printf("[027] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_stmt_close($stmt);
+
+ if (NULL !== ($tmp = mysqli_stmt_execute($stmt)))
+ printf("[028] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Warning: mysqli_stmt_execute(): invalid object or resource mysqli_stmt
+ in %s on line %d
+
+Warning: mysqli_stmt_execute(): invalid object or resource mysqli_stmt
+ in %s on line %d
+bool(true)
+bool(true)
+[027] Expecting boolean/false, got boolean/1
+
+Warning: mysqli_stmt_execute(): Couldn't fetch mysqli_stmt in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_execute_stored_proc.phpt b/ext/mysqli/tests/mysqli_stmt_execute_stored_proc.phpt
new file mode 100644
index 0000000..29e3947
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_execute_stored_proc.phpt
@@ -0,0 +1,198 @@
+--TEST--
+mysqli_stmt_execute() - Stored Procedures
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+require_once('connect.inc');
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ die(sprintf('skip Cannot connect to MySQL, [%d] %s.', mysqli_connect_errno(), mysqli_connect_error()));
+}
+if (mysqli_get_server_version($link) <= 50000) {
+ die(sprintf('skip Needs MySQL 5.0+, found version %d.', mysqli_get_server_version($link)));
+}
+?>
+--FILE--
+<?php
+ require_once('connect.inc');
+ require_once('table.inc');
+
+ if (!mysqli_query($link, 'DROP PROCEDURE IF EXISTS p'))
+ printf("[009] [%d] %s.\n", mysqli_errno($link), mysqli_error($link));
+
+ if (mysqli_real_query($link, 'CREATE PROCEDURE p(OUT ver_param VARCHAR(25)) BEGIN SELECT VERSION() INTO ver_param; END;')) {
+ /* no result set, one output parameter */
+ if (!$stmt = mysqli_prepare($link, 'CALL p(@version)'))
+ printf("[011] Cannot prepare CALL, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_stmt_execute($stmt))
+ printf("[012] Cannot execute CALL, [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ /* yes, I really want to call it twice! */
+ if (!mysqli_stmt_execute($stmt))
+ printf("[013] Cannot execute CALL, [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_close($stmt))
+ printf("[014] Cannot close statement, [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!$stmt = mysqli_prepare($link, 'SELECT @version AS _version'))
+ printf("[015] Cannot prepare SELECT, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_stmt_execute($stmt))
+ printf("[016] Cannot execute SELECT, [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $version = 'unknown';
+ if (!mysqli_stmt_bind_result($stmt, $version) ||
+ !mysqli_stmt_fetch($stmt))
+ printf("[017] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (($version == "unknown") || ($version == ""))
+ printf("[018] Results seem wrong, got %s, [%d] %s\n",
+ $version,
+ mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ mysqli_stmt_free_result($stmt);
+ mysqli_stmt_close($stmt);
+
+ } else {
+ printf("[010] Cannot create SP, [%d] %s.\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+
+ if (function_exists('mysqli_stmt_get_result')) {
+
+ if (!mysqli_query($link, 'DROP PROCEDURE IF EXISTS p'))
+ printf("[019] [%d] %s.\n", mysqli_errno($link), mysqli_error($link));
+
+ if (mysqli_real_query($link, 'CREATE PROCEDURE p(OUT ver_param VARCHAR(25)) BEGIN SELECT VERSION() INTO ver_param; END;')) {
+ // no result set, one output parameter
+ if (!$stmt = mysqli_prepare($link, 'CALL p(@version)'))
+ printf("[020] Cannot prepare CALL, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_stmt_execute($stmt))
+ printf("[021] Cannot execute CALL, [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_close($stmt))
+ printf("[022] Cannot close statement, [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!$stmt = mysqli_prepare($link, 'SELECT @version AS _version'))
+ printf("[023] Cannot prepare SELECT, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_stmt_execute($stmt))
+ printf("[024] Cannot execute SELECT, [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!$res = mysqli_stmt_get_result($stmt))
+ printf("[025] Cannot get result set, [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if ((!($row = mysqli_fetch_assoc($res))) || ($row['_version'] == ""))
+ printf("[026] Results seem wrong, got %s, [%d] %s\n",
+ $row['_version'],
+ mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ mysqli_free_result($res);
+ mysqli_stmt_close($stmt);
+
+ } else {
+ printf("[027] Cannot create SP, [%d] %s.\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ }
+
+ if (!mysqli_query($link, 'DROP PROCEDURE IF EXISTS p'))
+ printf("[028] [%d] %s.\n", mysqli_errno($link), mysqli_error($link));
+
+ if (mysqli_real_query($link, 'CREATE PROCEDURE p(IN ver_in VARCHAR(25), OUT ver_out VARCHAR(25)) BEGIN SELECT ver_in INTO ver_out; END;')) {
+ // no result set, one input parameter, output parameter
+ // yes, I really do not want to bind input values...
+ if (!$stmt = mysqli_prepare($link, "CALL p('myversion', @version)"))
+ printf("[029] Cannot prepare CALL, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_stmt_execute($stmt))
+ printf("[030] Cannot execute CALL, [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_close($stmt))
+ printf("[031] Cannot close statement, [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!$stmt = mysqli_prepare($link, 'SELECT @version AS _version'))
+ printf("[032] Cannot prepare SELECT, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_stmt_execute($stmt))
+ printf("[033] Cannot execute SELECT, [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $version = 'unknown';
+ if (!mysqli_stmt_bind_result($stmt, $version) ||
+ !mysqli_stmt_fetch($stmt))
+ printf("[034] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if ($version != "myversion")
+ printf("[035] Results seem wrong, got %s, [%d] %s\n",
+ $version,
+ mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ mysqli_stmt_free_result($stmt);
+ mysqli_stmt_close($stmt);
+
+ } else {
+ printf("[036] Cannot create SP, [%d] %s.\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ if (!mysqli_query($link, 'DROP PROCEDURE IF EXISTS p'))
+ printf("[037] [%d] %s.\n", mysqli_errno($link), mysqli_error($link));
+
+ if (mysqli_real_query($link, 'CREATE PROCEDURE p(IN ver_in VARCHAR(25), OUT ver_out VARCHAR(25)) BEGIN SELECT ver_in INTO ver_out; END;')) {
+ // no result set, one input parameter, output parameter
+ // yes, I really do not want to bind input values...
+ if (!$stmt = mysqli_prepare($link, 'CALL p(?, @version)'))
+ printf("[038] Cannot prepare CALL, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $version = 'myversion';
+ if (!mysqli_stmt_bind_param($stmt, 's', $version))
+ printf("[039] Cannot bind input parameter, [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_execute($stmt))
+ printf("[040] Cannot execute CALL, [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_close($stmt))
+ printf("[041] Cannot close statement, [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!$stmt = mysqli_prepare($link, 'SELECT @version AS _version'))
+ printf("[042] Cannot prepare SELECT, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_stmt_execute($stmt))
+ printf("[043] Cannot execute SELECT, [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $version = 'unknown';
+ if (!mysqli_stmt_bind_result($stmt, $version) ||
+ !mysqli_stmt_fetch($stmt))
+ printf("[044] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if ($version !== "myversion")
+ printf("[045] Results seem wrong, got %s, [%d] %s\n",
+ $version,
+ mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ mysqli_stmt_free_result($stmt);
+ mysqli_stmt_close($stmt);
+
+ } else {
+ printf("[046] Cannot create SP, [%d] %s.\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS test_bind_fetch"))
+ printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+@mysqli_query($link, 'DROP PROCEDURE IF EXISTS p');
+
+mysqli_close($link);
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_execute_stored_proc_next_result.phpt b/ext/mysqli/tests/mysqli_stmt_execute_stored_proc_next_result.phpt
new file mode 100644
index 0000000..35433b1
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_execute_stored_proc_next_result.phpt
@@ -0,0 +1,131 @@
+--TEST--
+mysqli_stmt_execute() - SP, next result
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+require_once('connect.inc');
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ die(sprintf('skip Cannot connect to MySQL, [%d] %s.', mysqli_connect_errno(), mysqli_connect_error()));
+}
+if (mysqli_get_server_version($link) < 50503) {
+ die(sprintf('skip Needs MySQL 5.5.3+, found version %d.', mysqli_get_server_version($link)));
+}
+?>
+--FILE--
+<?php
+ require_once('connect.inc');
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ printf("[001] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+ }
+
+ if (!mysqli_query($link, 'DROP PROCEDURE IF EXISTS p'))
+ printf("[003] [%d] %s.\n", mysqli_errno($link), mysqli_error($link));
+
+ if (mysqli_real_query($link, 'CREATE PROCEDURE p(IN ver_in VARCHAR(25)) BEGIN SELECT ver_in AS _ver_out; END;')) {
+ // one result set
+ if (!$stmt = mysqli_prepare($link, 'CALL p(?)'))
+ printf("[005] Cannot prepare CALL, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $version = 'myversion';
+ if (!mysqli_stmt_bind_param($stmt, 's', $version))
+ printf("[006] Cannot bind input parameter, [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_execute($stmt))
+ printf("[007] Cannot execute CALL, [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $version = 'unknown';
+ if (!mysqli_stmt_bind_result($stmt, $version) ||
+ !mysqli_stmt_fetch($stmt))
+ printf("[008] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if ($version !== "myversion")
+ printf("[009] Results seem wrong, got %s, [%d] %s\n",
+ $version,
+ mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ mysqli_stmt_free_result($stmt);
+
+ printf("[010] More results: %s\n", (mysqli_more_results($link)) ? "yes" : "no");
+ printf("[011] Next result: %s\n", (mysqli_next_result($link)) ? "yes" : "no");
+
+ if (!mysqli_stmt_close($stmt))
+ printf("[012] Cannot close statement, [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!$link->query("SELECT 1"))
+ printf("[013] [%d] %s\n", $link->errno, $link->error);
+
+ } else {
+ printf("[004] Cannot create SP, [%d] %s.\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ if (!mysqli_query($link, 'DROP PROCEDURE IF EXISTS p'))
+ printf("[014] [%d] %s.\n", mysqli_errno($link), mysqli_error($link));
+
+ if (mysqli_real_query($link, 'CREATE PROCEDURE p(IN ver_in VARCHAR(25)) BEGIN SELECT ver_in AS _ver_out; SELECT 1 AS _more; END;')) {
+ // two result sets
+ if (!$stmt = mysqli_prepare($link, 'CALL p(?)'))
+ printf("[015] Cannot prepare CALL, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $version = 'myversion';
+ if (!mysqli_stmt_bind_param($stmt, 's', $version))
+ printf("[016] Cannot bind input parameter, [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_execute($stmt))
+ printf("[017] Cannot execute CALL, [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $version = NULL;
+ if (!mysqli_stmt_bind_result($stmt, $version) ||
+ !mysqli_stmt_fetch($stmt))
+ printf("[018] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if ($version !== "myversion")
+ printf("[019] Results seem wrong, got %s, [%d] %s\n",
+ $version,
+ mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_more_results($link) || !mysqli_next_result($link))
+ printf("[020] [%d] %s\n", $link->errno, $link->error);
+
+ $more = NULL;
+ if (!mysqli_stmt_bind_result($stmt, $more) ||
+ !mysqli_stmt_fetch($stmt))
+ printf("[021] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if ($more !== 1)
+ printf("[022] Results seem wrong, got %s, [%d] %s\n",
+ $more,
+ mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_close($stmt))
+ printf("[023] Cannot close statement, [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+
+ if (!$link->query("SELECT 1"))
+ printf("[024] [%d] %s\n", $link->errno, $link->error);
+
+ } else {
+ printf("[025] Cannot create SP, [%d] %s.\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+@mysqli_query($link, 'DROP PROCEDURE IF EXISTS p');
+
+mysqli_close($link);
+?>
+--XFAIL--
+Unsupported and undefined, under development
+--EXPECTF--
+[010] More results: yes
+[011] Next result: yes
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_execute_stored_proc_out.phpt b/ext/mysqli/tests/mysqli_stmt_execute_stored_proc_out.phpt
new file mode 100644
index 0000000..8c7c799
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_execute_stored_proc_out.phpt
@@ -0,0 +1,81 @@
+--TEST--
+mysqli_stmt_execute() - OUT
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+require_once('connect.inc');
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ die(sprintf('skip Cannot connect to MySQL, [%d] %s.', mysqli_connect_errno(), mysqli_connect_error()));
+}
+if (mysqli_get_server_version($link) < 50503) {
+ die(sprintf('skip Needs MySQL 5.5.3+, found version %d.', mysqli_get_server_version($link)));
+}
+/*
+if ($IS_MYSQLND) {
+ die(sprintf("skip WHY ?!"));
+}
+*/
+?>
+--FILE--
+<?php
+ require_once('connect.inc');
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ printf("[001] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+ }
+
+ if (!mysqli_query($link, 'DROP PROCEDURE IF EXISTS p'))
+ printf("[003] [%d] %s.\n", mysqli_errno($link), mysqli_error($link));
+
+ if (mysqli_real_query($link, 'CREATE PROCEDURE p(IN ver_in VARCHAR(25), OUT ver_out VARCHAR(25)) BEGIN SELECT ver_in INTO ver_out; END;')) {
+ if (!$stmt = mysqli_prepare($link, 'CALL p(?, ?)'))
+ printf("[005] Cannot prepare CALL, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $ver_in = 'myversion';
+ $ver_out = '';
+ if (!mysqli_stmt_bind_param($stmt, 'ss', $ver_in, $ver_out))
+ printf("[006] Cannot bind parameter, [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_execute($stmt))
+ printf("[007] Cannot execute CALL, [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ printf("[008] More results: %s\n", (mysqli_more_results($link) ? "yes" : "no"));
+ printf("[009] Next results: %s\n", (mysqli_next_result($link) ? "yes" : "no"));
+
+ if (!mysqli_stmt_bind_result($stmt, $ver_out) || !mysqli_stmt_fetch($stmt))
+ printf("[010] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if ("myversion" !== $ver_out)
+ printf("[011] Results seem wrong got '%s'\n", $ver_out);
+
+ if (!mysqli_stmt_close($stmt))
+ printf("[012] Cannot close statement, [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!$res = $link->query("SELECT 1"))
+ printf("[013] [%d] %s\n", $link->errno, $link->error);
+
+ } else {
+ printf("[004] Cannot create SP, [%d] %s.\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+require_once("connect.inc");
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+@mysqli_query($link, 'DROP PROCEDURE IF EXISTS p');
+
+mysqli_close($link);
+?>
+--XFAIL--
+Unsupported and undefined, under development
+--EXPECTF--
+[008] More results: %s
+[009] Next results: %s
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_fetch.phpt b/ext/mysqli/tests/mysqli_stmt_fetch.phpt
new file mode 100644
index 0000000..7598ffe
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_fetch.phpt
@@ -0,0 +1,98 @@
+--TEST--
+mysqli_stmt_fetch()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ /*
+ NOTE: no datatype tests here! This is done by
+ mysqli_stmt_bind_result.phpt already. Restrict
+ this test case to the basics.
+ */
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_stmt_fetch()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_fetch($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ // stmt object status test
+ if (NULL !== ($tmp = mysqli_stmt_fetch($stmt)))
+ printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_prepare($stmt, "SELECT id, label FROM test ORDER BY id LIMIT 2"))
+ printf("[005] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ // FIXME - different versions return different values ?!
+ if ((NULL !== ($tmp = mysqli_stmt_fetch($stmt))) && (false !== $tmp))
+ printf("[006] Expecting NULL or boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_execute($stmt))
+ printf("[007] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (true !== ($tmp = mysqli_stmt_fetch($stmt)))
+ printf("[008] NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_stmt_close($stmt);
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[009] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_stmt_prepare($stmt, "SELECT id, label FROM test ORDER BY id LIMIT 2"))
+ printf("[010] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_execute($stmt))
+ printf("[011] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = NULL;
+ $label = NULL;
+ if (true !== ($tmp = mysqli_stmt_bind_result($stmt, $id, $label)))
+ printf("[012] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (true !== ($tmp = mysqli_stmt_fetch($stmt)))
+ printf("[013] Expecting boolean/true, got %s/%s, [%d] %s\n",
+ gettype($tmp), $tmp, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_kill($link, mysqli_thread_id($link)))
+ printf("[014] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (true !== ($tmp = mysqli_stmt_fetch($stmt)))
+ printf("[015] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_stmt_close($stmt);
+
+ if (NULL !== ($tmp = mysqli_stmt_fetch($stmt)))
+ printf("[016] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_close($link);
+
+ /* Check that the function alias exists. It's a deprecated function,
+ but we have not announce the removal so far, therefore we need to check for it */
+ if (!is_null($tmp = @mysqli_stmt_fetch()))
+ printf("[017] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Warning: mysqli_stmt_fetch(): invalid object or resource mysqli_stmt
+ in %s on line %d
+[014] [%d] Commands out of sync; you can't run this command now
+
+Warning: mysqli_stmt_fetch(): Couldn't fetch mysqli_stmt in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_fetch_bit.phpt b/ext/mysqli/tests/mysqli_stmt_fetch_bit.phpt
new file mode 100644
index 0000000..2a2914a
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_fetch_bit.phpt
@@ -0,0 +1,76 @@
+--TEST--
+Fetching BIT column values using the PS API
+--SKIPIF--
+<?php
+ require_once('skipif.inc');
+ require_once('skipifemb.inc');
+ require_once('skipifconnectfailure.inc');
+ require_once('connect.inc');
+ require_once('table.inc');
+ if (mysqli_get_server_version($link) < 50003)
+ // b'001' syntax not supported before 5.0.3
+ die("skip Syntax used for test not supported with MySQL Server before 5.0.3");
+ if (!$IS_MYSQLND && (mysqli_get_client_version() < 50003))
+ // better don't trust libmysql before 5.0.3
+ die("skip Syntax used for test not supported with MySQL Server before 5.0.3");
+?>
+--FILE--
+<?php
+ require('connect.inc');
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[001] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ /* NOTE: works only for up to 31 bits! This limitation should be documented. */
+ for ($bits = 1; $bits < 32; $bits++) {
+ $max_value = pow(2, $bits) - 1;
+ $tests = 0;
+ if (!mysqli_query($link, "DROP TABLE IF EXISTS test") ||
+ !mysqli_query($link, $sql = sprintf('CREATE TABLE test(id INT, label BIT(%d)) ENGINE="%s"', $bits, $engine)))
+ printf("[002 - %d] [%d] %s\n",$bits, mysqli_errno($link), mysqli_error($link));
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[003 - %d] [%d] %s\n", $bits, mysqli_errno($link), mysqli_error($link));
+
+ while ($tests < min($max_value, 20)) {
+ $tests++;
+ $value = mt_rand(0, $max_value);
+ $sql = sprintf("INSERT INTO test(id, label) VALUES (%d, b'%s')", $value, decbin($value));
+
+ if (!mysqli_stmt_prepare($stmt, $sql) ||
+ !mysqli_stmt_execute($stmt))
+ printf("[004 - %d] [%d] %s\n", $bits, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = $_label0 = $label = null;
+ $sql = sprintf("SELECT id, label + 0 AS _label0, label FROM test WHERE id = %d", $value);
+ if (!mysqli_stmt_prepare($stmt, $sql) ||
+ !mysqli_stmt_execute($stmt) ||
+ !mysqli_stmt_bind_result($stmt, $id, $_label0, $label))
+ printf("[005 - %d] [%d] %s\n", $bits, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_fetch($stmt))
+ printf("[006 - %d] [%d] %s\n", $bits, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (($id !== $_label0) || ($value !== $_label0)) {
+ printf("[007 - %d] Insert of %d in BIT(%d) column might have failed. MySQL reports odd values, id = %s, _label0 = %s, label = %s.\n", $bits, $value, $bits, $id, $_label0, $label);
+ }
+ if ($value != $label) {
+ printf("[008 - %d] Wrong values, (original) value = %s, id = %s, label + 0 AS label0 = %s, label = %s\n",
+ $bits, $value, $id, $_label0, $label);
+ }
+ }
+
+ mysqli_stmt_close($stmt);
+
+ }
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_fetch_fields_win32_unicode.phpt b/ext/mysqli/tests/mysqli_stmt_fetch_fields_win32_unicode.phpt
new file mode 100644
index 0000000..0cbc05f
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_fetch_fields_win32_unicode.phpt
@@ -0,0 +1,56 @@
+--TEST--
+mysqli_stmt_fetch_fields() unicode, win32
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+ require_once('table.inc');
+
+ $bind_res = $id = null;
+ if (!($stmt = mysqli_stmt_init($link)) ||
+ !mysqli_stmt_prepare($stmt, "SELECT id, label FROM test") ||
+ !mysqli_stmt_execute($stmt) ||
+ !($result = mysqli_stmt_result_metadata($stmt)) ||
+ !mysqli_stmt_bind_result($stmt, $id, $bind_res) ||
+ !($fields = mysqli_fetch_fields($result))) {
+ printf("FAIL 1\n");
+ }
+ while (mysqli_stmt_fetch($stmt)) {
+ ;
+ }
+ mysqli_free_result($result);
+ mysqli_stmt_close($stmt);
+
+ if (!($stmt = mysqli_stmt_init($link)) ||
+ !mysqli_stmt_prepare($stmt, "SELECT id, label FROM test") ||
+ !mysqli_stmt_execute($stmt) ||
+ !($result = mysqli_stmt_result_metadata($stmt)) ||
+ !mysqli_stmt_bind_result($stmt, $id, $bind_res)) {
+ printf("FAIL 2\n");
+ }
+ print "OK: 1\n";
+ if (!($fields = mysqli_fetch_fields($result)))
+ printf("Aua 3\n");
+ print "OK: 2\n";
+ while (mysqli_stmt_fetch($stmt)) {
+ ;
+ }
+ mysqli_free_result($result);
+ mysqli_stmt_close($stmt);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+OK: 1
+OK: 2
+done!
diff --git a/ext/mysqli/tests/mysqli_stmt_fetch_geom.phpt b/ext/mysqli/tests/mysqli_stmt_fetch_geom.phpt
new file mode 100644
index 0000000..84998b9
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_fetch_geom.phpt
@@ -0,0 +1,141 @@
+--TEST--
+mysqli_stmt_fetch - geometry / spatial types
+--SKIPIF--
+<?php
+ require_once('skipif.inc');
+ require_once('skipifemb.inc');
+ require_once('skipifconnectfailure.inc');
+
+ if (!defined("MYSQLI_TYPE_GEOMETRY"))
+ die("skip MYSQLI_TYPE_GEOMETRY not defined");
+?>
+--FILE--
+<?php
+ require('connect.inc');
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+ function func_mysqli_stmt_fetch_geom($link, $engine, $sql_type, $bind_value, $offset) {
+
+ if (!mysqli_query($link, "DROP TABLE IF EXISTS test")) {
+ printf("[%04d] [%d] %s\n", $offset, mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ if (!mysqli_query($link, sprintf("CREATE TABLE test(id INT, label %s, PRIMARY KEY(id)) ENGINE = %s", $sql_type, $engine))) {
+ // don't bail - column type might not be supported by the server, ignore this
+ return false;
+ }
+
+ for ($id = 1; $id < 4; $id++) {
+ $sql = sprintf("INSERT INTO test(id, label) VALUES (%d, %s)", $id, $bind_value);
+ if (!mysqli_query($link, $sql)) {
+ printf("[%04d] [%d] %s\n", $offset + 2 + $id, mysqli_errno($link), mysqli_error($link));
+ }
+ }
+
+ if (!$stmt = mysqli_stmt_init($link)) {
+ printf("[%04d] [%d] %s\n", $offset + 6, mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ if (!mysqli_stmt_prepare($stmt, "SELECT id, label FROM test")) {
+ printf("[%04d] [%d] %s\n", $offset + 7, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ mysqli_stmt_close($stmt);
+ return false;
+ }
+
+ if (!mysqli_stmt_execute($stmt) || !mysqli_stmt_store_result($stmt)) {
+ printf("[%04d] [%d] %s\n", $offset + 8, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ mysqli_stmt_close($stmt);
+ return false;
+ }
+
+ if (!mysqli_stmt_bind_result($stmt, $id, $bind_res)) {
+ printf("[%04d] [%d] %s\n", $offset + 9, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ mysqli_stmt_close($stmt);
+ return false;
+ }
+
+ $result = mysqli_stmt_result_metadata($stmt);
+ $fields = mysqli_fetch_fields($result);
+ if ($fields[1]->type != MYSQLI_TYPE_GEOMETRY) {
+ printf("[%04d] [%d] %s wrong type %d\n", $offset + 10, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt), $fields[1]->type);
+ }
+
+ $num = 0;
+ $rows = array();
+ while (true === @mysqli_stmt_fetch($stmt)) {
+ $rows[] = array('id' => $id, 'label' => $bind_res);
+ $num++;
+ }
+
+ if ($num != 3) {
+ printf("[%04d] [%d] %s, expecting 3 results, got only %d results\n",
+ $offset + 17, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt), $num);
+ return false;
+ }
+ mysqli_stmt_close($stmt);
+
+ foreach ($rows as $row) {
+ if (!$stmt = mysqli_stmt_init($link)) {
+ printf("[%04d] [%d] %s\n", $offset + 10, mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ if (!mysqli_stmt_prepare($stmt, "INSERT INTO test(id, label) VALUES (?, ?)")) {
+ printf("[%04d] [%d] %s\n", $offset + 11, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ return false;
+ }
+
+ $new_id = $row['id'] + 10;
+ if (!mysqli_stmt_bind_param($stmt, "is", $new_id, $row['label'])) {
+ printf("[%04d] [%d] %s\n", $offset + 12, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ return false;
+ }
+
+ if (!mysqli_stmt_execute($stmt)) {
+ printf("[%04d] [%d] %s\n", $offset + 13, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ return false;
+ }
+ mysqli_stmt_close($stmt);
+
+ if (!$res_normal = mysqli_query($link, sprintf("SELECT id, label FROM test WHERE id = %d",
+ $new_id))) {
+ printf("[%04d] [%d] %s\n", $offset + 14, mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ if (!$row_normal = mysqli_fetch_assoc($res_normal)) {
+ printf("[%04d] [%d] %s\n", $offset + 15, mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ if ($row_normal['label'] != $row['label']) {
+ printf("[%04d] PS and non-PS return different data.\n", $offset + 16);
+ return false;
+ }
+ mysqli_free_result($res_normal);
+ }
+
+ return true;
+ }
+
+ func_mysqli_stmt_fetch_geom($link, $engine, "GEOMETRY", "GeomFromText('POINT(2 2)')", 20);
+ func_mysqli_stmt_fetch_geom($link, $engine, "POINT", "GeomFromText('POINT(1 1)')", 40);
+ func_mysqli_stmt_fetch_geom($link, $engine, "LINESTRING", "GeomFromText('LINESTRING(0 0,1 1,2 2)')", 60);
+ func_mysqli_stmt_fetch_geom($link, $engine, "POLYGON", "GeomFromText('POLYGON((0 0,10 0,10 10,0 10,0 0),(5 5,7 5,7 7,5 7, 5 5))')", 80);
+ func_mysqli_stmt_fetch_geom($link, $engine, "MULTIPOINT", "GeomFromText('MULTIPOINT(1 1, 2 2)')", 100);
+ func_mysqli_stmt_fetch_geom($link, $engine, "MULTILINESTRING", "GeomFromText('MULTILINESTRING((0 0,1 1,2 2),(0 0,1 1,3 3))')", 120);
+ func_mysqli_stmt_fetch_geom($link, $engine, "MULTIPOLYGON", "GeomFromText('MULTIPOLYGON(((0 0,10 0,10 10,0 10,0 0),(5 5,7 5,7 7,5 7, 5 5)),((0 0,10 0,10 10,0 10,0 0),(5 5,7 5,7 7,5 7, 5 5)))')", 140);
+ func_mysqli_stmt_fetch_geom($link, $engine, "GEOMETRYCOLLECTION", "GeomFromText('GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(0 0,1 1,2 2,3 3,4 4))')", 160);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_field_count.phpt b/ext/mysqli/tests/mysqli_stmt_field_count.phpt
new file mode 100644
index 0000000..7dfd3a4
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_field_count.phpt
@@ -0,0 +1,100 @@
+--TEST--
+mysqli_stmt_field_counts()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_stmt_field_count()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_field_count($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ $stmt = mysqli_stmt_init($link);
+ if (!is_null($tmp = mysqli_stmt_field_count($stmt)))
+ printf("[003] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (mysqli_stmt_prepare($stmt, ''))
+ printf("[004] Prepare should fail for an empty statement\n");
+ if (!is_null($tmp = mysqli_stmt_field_count($stmt)))
+ printf("[005] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_prepare($stmt, 'SELECT 1'))
+ printf("[006] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ if (1 !== ($tmp = mysqli_stmt_field_count($stmt)))
+ printf("[007] Expecting int/1, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_prepare($stmt, 'SELECT 1, 2'))
+ printf("[008] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ if (2 !== ($tmp = mysqli_stmt_field_count($stmt)))
+ printf("[009] Expecting int/2, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_prepare($stmt, 'SELECT id, label FROM test'))
+ printf("[010] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ if (2 !== ($tmp = mysqli_stmt_field_count($stmt)))
+ printf("[011] Expecting int/2, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_prepare($stmt, 'SELECT label FROM test') ||
+ !mysqli_stmt_execute($stmt))
+ printf("[012] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ if (1 !== ($tmp = mysqli_stmt_field_count($stmt)))
+ printf("[013] Expecting int/1, got %s/%s\n", gettype($tmp), $tmp);
+
+ $label = null;
+ if (mysqli_stmt_bind_param($stmt, "s", $label))
+ printf("[014] expected error - got ok\n");
+ while (mysqli_stmt_fetch($stmt))
+ if (1 !== ($tmp = mysqli_stmt_field_count($stmt)))
+ printf("[015] Expecting int/1, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_prepare($stmt, 'INSERT INTO test(id) VALUES (100)'))
+ printf("[016] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ if (0 !== ($tmp = mysqli_stmt_field_count($stmt)))
+ printf("[017] Expecting int/0, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_prepare($stmt, "UPDATE test SET label = 'z' WHERE id = 1") ||
+ !mysqli_stmt_execute($stmt))
+ printf("[018] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (0 !== ($tmp = mysqli_stmt_field_count($stmt)))
+ printf("[019] Expecting int/0, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_stmt_close($stmt);
+
+ if (mysqli_stmt_prepare($stmt, 'SELECT id FROM test'))
+ printf("[020] Prepare should fail, statement has been closed\n");
+ if (!is_null($tmp = mysqli_stmt_field_count($stmt)))
+ printf("[011] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_close($link);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Warning: mysqli_stmt_field_count(): invalid object or resource mysqli_stmt
+ in %s on line %d
+
+Warning: mysqli_stmt_field_count(): invalid object or resource mysqli_stmt
+ in %s on line %d
+
+Warning: mysqli_stmt_bind_param(): Number of variables doesn't match number of parameters in prepared statement in %s on line %d
+
+Warning: mysqli_stmt_prepare(): Couldn't fetch mysqli_stmt in %s on line %d
+
+Warning: mysqli_stmt_field_count(): Couldn't fetch mysqli_stmt in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_free_result.phpt b/ext/mysqli/tests/mysqli_stmt_free_result.phpt
new file mode 100644
index 0000000..08b33b7
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_free_result.phpt
@@ -0,0 +1,86 @@
+--TEST--
+mysqli_stmt_free_result()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ /*
+ NOTE: no datatype tests here! This is done by
+ mysqli_stmt_bind_result.phpt already. Restrict
+ this test case to the basics.
+ */
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_stmt_free_result()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_free_result($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ // stmt object status test
+ if (NULL !== ($tmp = mysqli_stmt_free_result($stmt)))
+ printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_prepare($stmt, "SELECT id, label FROM test ORDER BY id"))
+ printf("[005] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (NULL !== ($tmp = mysqli_stmt_free_result($stmt)))
+ printf("[006] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_execute($stmt))
+ printf("[007] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (NULL !== ($tmp = mysqli_stmt_free_result($stmt)))
+ printf("[008] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (false !== ($tmp = mysqli_stmt_store_result($stmt)))
+ printf("[009] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_stmt_close($stmt);
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[010] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_stmt_prepare($stmt, "SELECT id, label FROM test ORDER BY id"))
+ printf("[011] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_execute($stmt))
+ printf("[012] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (true !== ($tmp = mysqli_stmt_store_result($stmt)))
+ printf("[013] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (NULL !== ($tmp = mysqli_stmt_free_result($stmt)))
+ printf("[014] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_stmt_close($stmt);
+
+ if (NULL !== ($tmp = mysqli_stmt_free_result($stmt)))
+ printf("[015] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_close($link);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Warning: mysqli_stmt_free_result(): invalid object or resource mysqli_stmt
+ in %s on line %d
+
+Warning: mysqli_stmt_free_result(): Couldn't fetch mysqli_stmt in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_get_result.phpt b/ext/mysqli/tests/mysqli_stmt_get_result.phpt
new file mode 100644
index 0000000..fe18be4
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_get_result.phpt
@@ -0,0 +1,187 @@
+--TEST--
+mysqli_stmt_get_result()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+if (!function_exists('mysqli_stmt_get_result'))
+ die('skip mysqli_stmt_get_result not available');
+?>
+--FILE--
+<?php
+ /*
+ NOTE: no datatype tests here! This is done by
+ mysqli_stmt_bind_result.phpt already. Restrict
+ this test case to the basics.
+ */
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_stmt_get_result()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_get_result($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ // stmt object status test
+ if (NULL !== ($tmp = mysqli_stmt_fetch($stmt)))
+ printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), var_export($tmp, 1));
+
+ if (!mysqli_stmt_prepare($stmt, "SELECT id, label FROM test ORDER BY id LIMIT 2"))
+ printf("[005] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ // FIXME - different versions return different values ?!
+ if ((NULL !== ($tmp = mysqli_stmt_get_result($stmt))) && (false !== $tmp))
+ printf("[006] Expecting NULL or boolean/false, got %s/%s\n", gettype($tmp), var_export($tmp, 1));
+
+ if (!mysqli_stmt_execute($stmt))
+ printf("[007] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_store_result($stmt))
+ printf("[008] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (is_object($tmp = mysqli_stmt_store_result($stmt)))
+ printf("[009] non-object, got %s/%s\n", gettype($tmp), var_export($tmp, 1));
+
+ mysqli_stmt_close($stmt);
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[010] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ // stmt object status test
+ if (NULL !== ($tmp = mysqli_stmt_fetch($stmt)))
+ printf("[011] Expecting NULL, got %s/%s\n", gettype($tmp), var_export($tmp, 1));
+
+ if (!mysqli_stmt_prepare($stmt, "SELECT id, label FROM test ORDER BY id LIMIT 2"))
+ printf("[012] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ // FIXME - different versions return different values ?!
+ if ((NULL !== ($tmp = mysqli_stmt_get_result($stmt))) && (false !== $tmp))
+ printf("[013] Expecting NULL or boolean/false, got %s/%s\n", gettype($tmp), var_export($tmp, 1));
+
+ if (!mysqli_stmt_execute($stmt))
+ printf("[014] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!is_object($tmp = mysqli_stmt_get_result($stmt)))
+ printf("[016] NULL, got %s/%s\n", gettype($tmp), var_export($tmp, 1));
+
+ mysqli_free_result($tmp);
+ mysqli_stmt_close($stmt);
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[017] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ // stmt object status test
+ if (NULL !== ($tmp = mysqli_stmt_get_result($stmt)))
+ printf("[018] Expecting NULL, got %s/%s\n", gettype($tmp), var_export($tmp, 1));
+
+ if (!mysqli_stmt_prepare($stmt, "SELECT id, label FROM test ORDER BY id LIMIT 2"))
+ printf("[019] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (false !== ($tmp = mysqli_stmt_get_result($stmt)))
+ printf("[020] Expecting false, got %s/%s\n", gettype($tmp), var_export($tmp, 1));
+
+ if (!mysqli_stmt_execute($stmt))
+ printf("[023] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!is_object($tmp = mysqli_stmt_get_result($stmt)))
+ printf("[024] Expecting object, got %s/%s\n", gettype($tmp), var_export($tmp, 1));
+
+ if (false !== ($tmp = mysqli_stmt_fetch($stmt)))
+ printf("[025] false, got %s/%s\n", gettype($tmp), var_export($tmp, 1));
+
+ if (true !== ($tmp = mysqli_stmt_bind_result($stmt, $id, $label))) {
+ printf("[026] [%d] [%s]\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ printf("[027] [%d] [%s]\n", mysqli_errno($link), mysqli_error($link));
+ printf("[028] Expecting boolean/true, got %s/%s\n", gettype($tmp), var_export($tmp, 1));
+ }
+
+ if (false !== ($tmp = mysqli_stmt_fetch($stmt)))
+ printf("[029] false, got %s/%s\n", gettype($tmp), var_export($tmp, 1));
+
+ mysqli_stmt_close($stmt);
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[032] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_stmt_prepare($stmt, "SELECT id, label FROM test ORDER BY id LIMIT 2"))
+ printf("[033] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_execute($stmt))
+ printf("[034] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = NULL;
+ $label = NULL;
+ if (true !== ($tmp = mysqli_stmt_bind_result($stmt, $id, $label)))
+ printf("[035] Expecting boolean/true, got %s/%s\n", gettype($tmp), var_export($tmp, 1));
+
+ if (!is_object($tmp = $result = mysqli_stmt_get_result($stmt)))
+ printf("[036] Expecting array, got %s/%s, [%d] %s\n",
+ gettype($tmp), var_export($tmp, 1),
+ mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (false !== ($tmp = mysqli_stmt_fetch($stmt)))
+ printf("[037] Expecting boolean/false, got %s/%s, [%d] %s\n",
+ gettype($tmp), $tmp, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ printf("[038] [%d] [%s]\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ printf("[039] [%d] [%s]\n", mysqli_errno($link), mysqli_error($link));
+ while ($row = mysqli_fetch_assoc($result)) {
+ var_dump($row);
+ }
+ mysqli_free_result($result);
+
+ if (!mysqli_kill($link, mysqli_thread_id($link)))
+ printf("[040] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (false !== ($tmp = mysqli_stmt_get_result($stmt)))
+ printf("[041] Expecting false, got %s/%s\n", gettype($tmp), var_export($tmp, 1));
+
+ mysqli_stmt_close($stmt);
+
+ if (NULL !== ($tmp = mysqli_stmt_fetch($stmt)))
+ printf("[042] Expecting NULL, got %s/%s\n", gettype($tmp), var_export($tmp, 1));
+
+ mysqli_close($link);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Warning: mysqli_stmt_fetch(): invalid object or resource mysqli_stmt
+ in %s on line %d
+
+Warning: mysqli_stmt_fetch(): invalid object or resource mysqli_stmt
+ in %s on line %d
+
+Warning: mysqli_stmt_get_result(): invalid object or resource mysqli_stmt
+ in %s on line %d
+[038] [2014] [Commands out of sync; you can't run this command now]
+[039] [0] []
+array(2) {
+ [%u|b%"id"]=>
+ int(1)
+ [%u|b%"label"]=>
+ %s(1) "a"
+}
+array(2) {
+ [%u|b%"id"]=>
+ int(2)
+ [%u|b%"label"]=>
+ %s(1) "b"
+}
+
+Warning: mysqli_stmt_fetch(): Couldn't fetch mysqli_stmt in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_get_result2.phpt b/ext/mysqli/tests/mysqli_stmt_get_result2.phpt
new file mode 100644
index 0000000..8c2aad1
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_get_result2.phpt
@@ -0,0 +1,176 @@
+--TEST--
+mysqli_stmt_get_result()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+if (!function_exists('mysqli_stmt_get_result'))
+ die('skip mysqli_stmt_get_result not available');
+?>
+--FILE--
+<?php
+ /*
+ NOTE: no datatype tests here! This is done by
+ mysqli_stmt_bind_result.phpt already. Restrict
+ this test case to the basics.
+ */
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_stmt_get_result()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_get_result($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!is_null($tmp = @mysqli_stmt_get_result($stmt, "foo")))
+ printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_prepare($stmt, "SELECT id, label FROM test ORDER BY id ASC LIMIT 1"))
+ printf("[005] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_execute($stmt))
+ printf("[006] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!is_object($res = mysqli_stmt_get_result($stmt)) || 'mysqli_result' != get_class($res)) {
+ printf("[007] Expecting object/mysqli_result got %s/%s, [%d] %s\n",
+ gettype($res), $res, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ }
+ while ($row = mysqli_fetch_assoc($res))
+ var_dump($row);
+ var_dump(mysqli_fetch_assoc($res));
+ mysqli_free_result($res);
+
+ if (false !== ($res = mysqli_stmt_get_result($stmt))) {
+ printf("[008] boolean/false got %s/%s, [%d] %s\n",
+ gettype($res), $res, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ }
+
+ mysqli_stmt_execute($stmt);
+ if (!is_object($res = mysqli_stmt_get_result($stmt)) || 'mysqli_result' != get_class($res)) {
+ printf("[009] Expecting object/mysqli_result got %s/%s, [%d] %s\n",
+ gettype($res), $res, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ }
+ while ($row = mysqli_fetch_assoc($res))
+ var_dump($row);
+ var_dump(mysqli_fetch_assoc($res));
+ mysqli_free_result($res);
+
+ mysqli_stmt_close($stmt);
+
+ if (!($stmt = mysqli_stmt_init($link)) ||
+ !mysqli_stmt_prepare($stmt, "SELECT id, label FROM test ORDER BY id ASC LIMIT 2") ||
+ !mysqli_stmt_execute($stmt))
+ printf("[010] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = $label = null;
+ if (!mysqli_stmt_bind_result($stmt, $id, $label))
+ printf("[011] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_fetch($stmt))
+ printf("[012] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (false !== ($res = mysqli_stmt_get_result($stmt))) {
+ printf("[013] boolean/false got %s/%s, [%d] %s\n",
+ gettype($res), $res, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ }
+
+ mysqli_stmt_close($stmt);
+
+ if (!($stmt = mysqli_stmt_init($link)) ||
+ !mysqli_stmt_prepare($stmt, "SELECT id, label FROM test ORDER BY id ASC LIMIT 2") ||
+ !mysqli_stmt_execute($stmt))
+ printf("[014] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!is_object($res = mysqli_stmt_get_result($stmt)) || 'mysqli_result' != get_class($res)) {
+ printf("[015] Expecting object/mysqli_result got %s/%s, [%d] %s\n",
+ gettype($res), $res, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ }
+
+ $id = $label = null;
+ if (!mysqli_stmt_bind_result($stmt, $id, $label))
+ printf("[016] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_fetch($stmt))
+ printf("[017] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ mysqli_stmt_close($stmt);
+
+ if (!($stmt = mysqli_stmt_init($link)) ||
+ !mysqli_stmt_prepare($stmt, "SELECT id, label FROM test ORDER BY id ASC LIMIT 2") ||
+ !mysqli_stmt_execute($stmt))
+ printf("[018] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!is_object($res = mysqli_stmt_get_result($stmt)) || 'mysqli_result' != get_class($res)) {
+ printf("[019] Expecting object/mysqli_result got %s/%s, [%d] %s\n",
+ gettype($res), $res, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ }
+
+ $id = $label = null;
+ if (!mysqli_stmt_bind_result($stmt, $id, $label))
+ printf("[020] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $row = mysqli_fetch_assoc($res);
+ if (NULL !== $id || NULL !== $label)
+ printf("[021] Bound variables should not have been set\n");
+ mysqli_free_result($res);
+
+ mysqli_stmt_close($stmt);
+
+ if (!($stmt = mysqli_stmt_init($link)) ||
+ !mysqli_stmt_prepare($stmt, "SELECT id, label FROM test ORDER BY id ASC LIMIT 2") ||
+ !mysqli_stmt_execute($stmt))
+ printf("[022] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!is_object($res = mysqli_stmt_get_result($stmt)) || 'mysqli_result' != get_class($res)) {
+ printf("[023] Expecting object/mysqli_result got %s/%s, [%d] %s\n",
+ gettype($res), $res, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ }
+ if (!in_array($res->type, array(MYSQLI_STORE_RESULT, MYSQLI_USE_RESULT))) {
+ printf("[024] Unknown result set type %s\n", $res->type);
+ }
+ if ($res->type !== MYSQLI_STORE_RESULT)
+ printf("[025] Expecting int/%d got %s/%s", MYSQLI_STORE_RESULT, gettype($res->type), $res->type);
+
+ mysqli_free_result($res);
+ mysqli_stmt_close($stmt);
+ mysqli_close($link);
+
+ if (NULL !== ($res = mysqli_stmt_get_result($stmt))) {
+ printf("[022] Expecting NULL got %s/%s\n",
+ gettype($res), $res);
+ }
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+array(2) {
+ [%u|b%"id"]=>
+ int(1)
+ [%u|b%"label"]=>
+ %unicode|string%(1) "a"
+}
+NULL
+array(2) {
+ [%u|b%"id"]=>
+ int(1)
+ [%u|b%"label"]=>
+ %unicode|string%(1) "a"
+}
+NULL
+[017] [2014] Commands out of sync; you can't run this command now
+
+Warning: mysqli_stmt_get_result(): Couldn't fetch mysqli_stmt in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_get_result_bit.phpt b/ext/mysqli/tests/mysqli_stmt_get_result_bit.phpt
new file mode 100644
index 0000000..6c476f7
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_get_result_bit.phpt
@@ -0,0 +1,133 @@
+--TEST--
+Fetching BIT column values using the PS API
+--SKIPIF--
+<?php
+ require_once('skipif.inc');
+ require_once('skipifemb.inc');
+ require_once('skipifconnectfailure.inc');
+
+ if (!function_exists('mysqli_stmt_get_result'))
+ die("skip mysqli_stmt_get_result() not available");
+
+ require_once('connect.inc');
+ require_once('table.inc');
+ if (mysqli_get_server_version($link) < 50003)
+ // b'001' syntax not supported before 5.0.3
+ die("skip Syntax used for test not supported with MySQL Server before 5.0.3");
+ if (!$IS_MYSQLND && (mysqli_get_client_version() < 50003))
+ // better don't trust libmysql before 5.0.3
+ die("skip Syntax used for test not supported with MySQL Server before 5.0.3");
+?>
+--FILE--
+<?php
+ require('connect.inc');
+
+ function dec32bin($dec, $bits) {
+
+ $maxval = pow(2, $bits);
+ $bin = '';
+ for ($bitval = $maxval; $bitval >= 1; $bitval = $bitval / 2) {
+ if (($dec / $bitval) >= 1) {
+ $bin .= '1';
+ $dec -= $bitval;
+ } else {
+ $bin .= '0';
+ }
+ }
+ return $bin;
+ }
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[001] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ for ($bits = 1; $bits <= 46; $bits++) {
+ if (1 == $bits)
+ $max_value = 1;
+ else
+ $max_value = pow(2, $bits) - 1;
+
+ if (!mysqli_query($link, "DROP TABLE IF EXISTS test") ||
+ !mysqli_query($link, $sql = sprintf('CREATE TABLE test(id BIGINT UNSIGNED, bit_value BIT(%d) NOT NULL, bit_null BIT(%d) DEFAULT NULL) ENGINE="%s"', $bits, $bits, $engine)))
+ printf("[002 - %d] [%d] %s\n",$bits, mysqli_errno($link), mysqli_error($link));
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[003 - %d] [%d] %s\n", $bits, mysqli_errno($link), mysqli_error($link));
+
+ $tests = 0;
+ $rand_max = mt_getrandmax();
+ while ($tests < 10) {
+
+ $tests++;
+ if (1 == $tests)
+ $value = 0;
+ else if (2 == $tests)
+ $value = $max_value;
+ else {
+ if ($max_value > $rand_max) {
+ $max_loops = floor($max_value/$rand_max);
+ $num_loops = mt_rand(1, $max_loops);
+ $value = 0;
+ for ($i = 0; $i < $num_loops; $i++)
+ $value += mt_rand(0, $rand_max);
+ } else {
+ $value = mt_rand(0, $max_value);
+ }
+ }
+
+ $bin = ($bits < 32) ? decbin($value) : dec32bin($value, $bits);
+ $sql = sprintf("INSERT INTO test(id, bit_value) VALUES (%s, b'%s')", $value, $bin);
+ for ($i = 0; ($i < strlen($bin)) && ($bin[$i] == '0'); $i++)
+ ;
+ $bin2 = substr($bin, $i, strlen($bin));
+
+ if (!mysqli_stmt_prepare($stmt, $sql) ||
+ !mysqli_stmt_execute($stmt))
+ printf("[004 - %d] [%d] %s\n", $bits, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $sql = sprintf("SELECT bin(bit_value) AS _bin, id, bit_value, bit_null FROM test WHERE id = %s", $value);
+ if (!mysqli_stmt_prepare($stmt, $sql) ||
+ !mysqli_stmt_execute($stmt))
+ printf("[005 - %d] [%d] %s\n", $bits, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!$res = mysqli_stmt_get_result($stmt))
+ printf("[006 - %d] [%d] %s\n", $bits, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!$row = mysqli_fetch_assoc($res))
+ printf("[007 - %d] [%d] %s\n", $bits, mysqli_errno($link), mysqli_error($link));
+ mysqli_free_result($res);
+
+ if (($value != $row['id']) || (($bin != $row['_bin']) && ($bin2 != $row['_bin']))) {
+ debug_zval_dump($row);
+ printf("[008 - %d] Insert of %s in BIT(%d) column might have failed. id = %s, bin = %s (%s/%s)\n",
+ $bits, $value, $bits, $row['id'], $row['_bin'], $bin, $bin2);
+ break;
+ }
+ if ($value != $row['bit_value']) {
+ debug_zval_dump($row);
+ printf("%10s %64s\n%10s %64s\n", '_bin', $row['_bin'], 'insert', $bin);
+ printf("[009 - %d] Expecting %s got %s\n", $bits, $value, $row['bit_value']);
+ break;
+ }
+
+ if (null !== $row['bit_null']) {
+ debug_zval_dump($row);
+ printf("[010 - %d] Expecting null got %s/%s\n", $bits, gettype($row['bit_value']), $row['bit_value']);
+ break;
+ }
+
+ }
+
+ mysqli_stmt_close($stmt);
+
+ }
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_get_result_field_count.phpt b/ext/mysqli/tests/mysqli_stmt_get_result_field_count.phpt
new file mode 100644
index 0000000..046f904
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_get_result_field_count.phpt
@@ -0,0 +1,50 @@
+--TEST--
+mysqli_stmt_get_result() - meta data, field_count()
+--SKIPIF--
+<?php
+ require_once('skipif.inc');
+ require_once('skipifemb.inc');
+ require_once('skipifconnectfailure.inc');
+
+ if (!function_exists('mysqli_stmt_get_result'))
+ die('skip mysqli_stmt_get_result not available');
+?>
+--FILE--
+<?php
+ require('table.inc');
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[001] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_stmt_prepare($stmt, "SELECT id, label FROM test ORDER BY id ASC LIMIT 3"))
+ printf("[002] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_execute($stmt))
+ printf("[003] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!is_object($res = mysqli_stmt_get_result($stmt)) || 'mysqli_result' != get_class($res)) {
+ printf("[004] Expecting object/mysqli_result got %s/%s, [%d] %s\n",
+ gettype($res), $res, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ }
+
+ if (!is_object($res_meta = mysqli_stmt_result_metadata($stmt)) ||
+ 'mysqli_result' != get_class($res_meta)) {
+ printf("[005] Expecting object/mysqli_result got %s/%s, [%d] %s\n",
+ gettype($res), $res, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ }
+
+ printf("%s %s\n",
+ $res_meta->field_count,
+ $res->field_count);
+
+ mysqli_stmt_close($stmt);
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+2 2
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_get_result_geom.phpt b/ext/mysqli/tests/mysqli_stmt_get_result_geom.phpt
new file mode 100644
index 0000000..c86a385
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_get_result_geom.phpt
@@ -0,0 +1,143 @@
+--TEST--
+mysqli_stmt_get_result - geometry / spatial types
+--SKIPIF--
+<?php
+ require_once('skipif.inc');
+ require_once('skipifemb.inc');
+ require_once('skipifconnectfailure.inc');
+
+ if (!function_exists('mysqli_stmt_get_result'))
+ die("skip mysqli_stmt_get_result() not available");
+
+ if (!defined("MYSQLI_TYPE_GEOMETRY"))
+ die("skip MYSQLI_TYPE_GEOMETRY not defined");
+?>
+--FILE--
+<?php
+ require('connect.inc');
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+ function func_mysqli_stmt_get_result_geom($link, $engine, $sql_type, $bind_value, $offset) {
+
+ if (!mysqli_query($link, "DROP TABLE IF EXISTS test")) {
+ printf("[%04d] [%d] %s\n", $offset, mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ if (!mysqli_query($link, sprintf("CREATE TABLE test(id INT, label %s, PRIMARY KEY(id)) ENGINE = %s", $sql_type, $engine))) {
+ // don't bail - column type might not be supported by the server, ignore this
+ return false;
+ }
+
+ for ($id = 1; $id < 4; $id++) {
+ $sql = sprintf("INSERT INTO test(id, label) VALUES (%d, %s)", $id, $bind_value);
+ if (!mysqli_query($link, $sql)) {
+ printf("[%04d] [%d] %s\n", $offset + 2 + $id, mysqli_errno($link), mysqli_error($link));
+ }
+ }
+
+ if (!$stmt = mysqli_stmt_init($link)) {
+ printf("[%04d] [%d] %s\n", $offset + 6, mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ if (!mysqli_stmt_prepare($stmt, "SELECT id, label FROM test")) {
+ printf("[%04d] [%d] %s\n", $offset + 7, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ mysqli_stmt_close($stmt);
+ return false;
+ }
+
+ if (!mysqli_stmt_execute($stmt)) {
+ printf("[%04d] [%d] %s\n", $offset + 8, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ mysqli_stmt_close($stmt);
+ return false;
+ }
+ if (!$res = mysqli_stmt_get_result($stmt)) {
+ printf("[%04d] [%d] %s\n", $offset + 9, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ mysqli_stmt_close($stmt);
+ return false;
+ }
+
+ $result = mysqli_stmt_result_metadata($stmt);
+ $fields = mysqli_fetch_fields($result);
+ if ($fields[1]->type != MYSQLI_TYPE_GEOMETRY) {
+ printf("[%04d] [%d] %s wrong type %d\n", $offset + 10, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt), $fields[1]->type);
+ }
+
+ $num = 0;
+ while ($row = mysqli_fetch_assoc($res)) {
+ $bind_res = &$row['label'];
+
+ if (!$stmt2 = mysqli_stmt_init($link)) {
+ printf("[%04d] [%d] %s\n", $offset + 11, mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ if (!mysqli_stmt_prepare($stmt2, "INSERT INTO test(id, label) VALUES (?, ?)")) {
+ printf("[%04d] [%d] %s\n", $offset + 12, mysqli_stmt_errno($stmt2), mysqli_stmt_error($stmt2));
+ return false;
+ }
+
+ $id = $row['id'] + 10;
+ if (!mysqli_stmt_bind_param($stmt2, "is", $id, $bind_res)) {
+ printf("[%04d] [%d] %s\n", $offset + 13, mysqli_stmt_errno($stmt2), mysqli_stmt_error($stmt2));
+ return false;
+ }
+
+ if (!mysqli_stmt_execute($stmt2)) {
+ printf("[%04d] [%d] %s\n", $offset + 14, mysqli_stmt_errno($stmt2), mysqli_stmt_error($stmt2));
+ return false;
+ }
+ mysqli_stmt_close($stmt2);
+
+ if (!$res_normal = mysqli_query($link, sprintf("SELECT id, label FROM test WHERE id = %d",
+ $row['id'] + 10))) {
+ printf("[%04d] [%d] %s\n", $offset + 15, mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ if (!$row_normal = mysqli_fetch_assoc($res_normal)) {
+ printf("[%04d] [%d] %s\n", $offset + 16, mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ if ($row_normal['label'] != $bind_res) {
+ printf("[%04d] PS and non-PS return different data.\n", $offset + 17);
+ return false;
+ }
+ mysqli_free_result($res_normal);
+ $num++;
+ }
+
+ if ($num != 3) {
+ printf("[%04d] [%d] %s, expecting 3 results, got only %d results\n",
+ $offset + 18, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt), $num);
+ mysqli_free_result($res);
+ mysqli_stmt_close($stmt);
+ return false;
+ }
+ mysqli_free_result($res);
+ mysqli_stmt_close($stmt);
+
+ return true;
+ }
+
+ func_mysqli_stmt_get_result_geom($link, $engine, "GEOMETRY", "GeomFromText('POINT(2 2)')", 20);
+ func_mysqli_stmt_get_result_geom($link, $engine, "POINT", "GeomFromText('POINT(1 1)')", 40);
+ func_mysqli_stmt_get_result_geom($link, $engine, "LINESTRING", "GeomFromText('LINESTRING(0 0,1 1,2 2)')", 60);
+ func_mysqli_stmt_get_result_geom($link, $engine, "POLYGON", "GeomFromText('POLYGON((0 0,10 0,10 10,0 10,0 0),(5 5,7 5,7 7,5 7, 5 5))')", 80);
+ func_mysqli_stmt_get_result_geom($link, $engine, "MULTIPOINT", "GeomFromText('MULTIPOINT(1 1, 2 2)')", 100);
+ func_mysqli_stmt_get_result_geom($link, $engine, "MULTILINESTRING", "GeomFromText('MULTILINESTRING((0 0,1 1,2 2),(0 0,1 1,3 3))')", 120);
+ func_mysqli_stmt_get_result_geom($link, $engine, "MULTIPOLYGON", "GeomFromText('MULTIPOLYGON(((0 0,10 0,10 10,0 10,0 0),(5 5,7 5,7 7,5 7, 5 5)),((0 0,10 0,10 10,0 10,0 0),(5 5,7 5,7 7,5 7, 5 5)))')", 140);
+ func_mysqli_stmt_get_result_geom($link, $engine, "GEOMETRYCOLLECTION", "GeomFromText('GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(0 0,1 1,2 2,3 3,4 4))')", 160);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_get_result_metadata.phpt b/ext/mysqli/tests/mysqli_stmt_get_result_metadata.phpt
new file mode 100644
index 0000000..8689880
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_get_result_metadata.phpt
@@ -0,0 +1,237 @@
+--TEST--
+mysqli_stmt_get_result() - meta data
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+if (!function_exists('mysqli_stmt_get_result'))
+ die('skip mysqli_stmt_get_result not available');
+?>
+--FILE--
+<?php
+ require('table.inc');
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[001] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_stmt_prepare($stmt, "SELECT id, label FROM test ORDER BY id ASC LIMIT 3"))
+ printf("[002] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_execute($stmt))
+ printf("[003] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!is_object($res = mysqli_stmt_get_result($stmt)) || 'mysqli_result' != get_class($res)) {
+ printf("[004] Expecting object/mysqli_result got %s/%s, [%d] %s\n",
+ gettype($res), $res, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ }
+
+ if (!is_object($res_meta = mysqli_stmt_result_metadata($stmt)) ||
+ 'mysqli_result' != get_class($res_meta)) {
+ printf("[005] Expecting object/mysqli_result got %s/%s, [%d] %s\n",
+ gettype($res), $res, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ }
+
+ var_dump(mysqli_fetch_assoc($res));
+ var_dump(mysqli_fetch_assoc($res_meta));
+
+ mysqli_free_result($res);
+ mysqli_free_result($res_meta);
+ mysqli_stmt_close($stmt);
+
+ // !mysqli_stmt_prepare($stmt, "SELECT id, label, id + 1 as _id, concat(label, '_') _label FROM test as _test ORDER BY id ASC LIMIT 3") ||
+ if (!($stmt = mysqli_stmt_init($link)) ||
+ !mysqli_stmt_prepare($stmt, "SELECT id , label, id + 1 AS _id, label AS _label, null AS _null, CONCAT(label, '_') _label_concat FROM test _test ORDER BY id ASC LIMIT 3") ||
+ !mysqli_stmt_execute($stmt))
+ printf("[006] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!is_object($res = mysqli_stmt_get_result($stmt)) || 'mysqli_result' != get_class($res)) {
+ printf("[007] Expecting object/mysqli_result got %s/%s, [%d] %s\n",
+ gettype($res), $res, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ }
+
+ if (!is_object($res_meta = mysqli_stmt_result_metadata($stmt)) ||
+ 'mysqli_result' != get_class($res_meta)) {
+ printf("[008] Expecting object/mysqli_result got %s/%s, [%d] %s\n",
+ gettype($res), $res, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ }
+
+ if (($tmp1 = mysqli_num_fields($res)) !== ($tmp2 = mysqli_num_fields($res_meta))) {
+ printf("[009] %s/%s !== %s/%s\n", gettype($tmp1), $tmp1, gettype($tmp2), $tmp2);
+ }
+
+ /*
+ if (($tmp1 = mysqli_field_count($link)) !== ($tmp2 = $res->field_count()))
+ printf("[010] %s/%s !== %s/%s\n", gettype($tmp1), $tmp1, gettype($tmp2), $tmp2);
+
+ if (($tmp1 = $res_meta->field_count()) !== $tmp2)
+ printf("[011] %s/%s !== %s/%s\n", gettype($tmp1), $tmp1, gettype($tmp2), $tmp2);
+ */
+
+ if (($tmp1 = mysqli_field_tell($res)) !== ($tmp2 = $res_meta->current_field))
+ printf("[012] %s/%s !== %s/%s\n", gettype($tmp1), $tmp1, gettype($tmp2), $tmp2);
+
+ if (0 !== $tmp1)
+ printf("[013] Expecting int/0 got %s/%s\n", gettype($tmp1), $tmp1);
+
+ $fields = array();
+ while ($info = $res->fetch_field())
+ $fields['res'][] = $info;
+ var_dump($info);
+ while ($info = $res_meta->fetch_field())
+ $fields['meta'][] = $info;
+ var_dump($info);
+ $fields['all_res'] = $res->fetch_fields();
+ $fields['all_meta'] = $res_meta->fetch_fields();
+
+ if (count($fields['res']) != count($fields['meta'])) {
+ printf("[014] stmt_get_result indicates %d fields, stmt_result_metadata indicates %d fields\n",
+ count($fields['res']),
+ count($fields['meta']));
+ }
+
+ foreach ($fields['res'] as $k => $info) {
+ printf("%s\n", $info->name);
+ if ($info->name !== $fields['meta'][$k]->name)
+ printf("[015 - %d] Expecting name %s/%s got %s/%s\n",
+ $k, gettype($info->name), $info->name, gettype($fields['meta'][$k]->name), $fields['meta'][$k]->name);
+
+ if ($info->orgname !== $fields['meta'][$k]->orgname)
+ printf("[016 - %d] Expecting orgname %s/%s got %s/%s\n",
+ $k, gettype($info->orgname), $info->orgname, gettype($fields['meta'][$k]->orgname), $fields['meta'][$k]->orgname);
+
+ if ($info->table !== $fields['meta'][$k]->table)
+ printf("[017 - %d] Expecting table %s/%s got %s/%s\n",
+ $k, gettype($info->table), $info->table, gettype($fields['meta'][$k]->table), $fields['meta'][$k]->table);
+
+ if ($info->orgtable !== $fields['meta'][$k]->orgtable)
+ printf("[018 - %d] Expecting orgtable %s/%s got %s/%s\n",
+ $k, gettype($info->orgtable), $info->orgtable, gettype($fields['meta'][$k]->orgtable), $fields['meta'][$k]->orgtable);
+
+ if ($info->def !== $fields['meta'][$k]->def)
+ printf("[019 - %d] Expecting def %s/%s got %s/%s\n",
+ $k, gettype($info->def), $info->def, gettype($fields['meta'][$k]->def), $fields['meta'][$k]->def);
+/*
+ if ($info->max_length !== $fields['meta'][$k]->max_length)
+ printf("[020 - %d] Expecting max_length %s/%s got %s/%s\n",
+ $k, gettype($info->max_length), $info->max_length, gettype($fields['meta'][$k]->max_length), $fields['meta'][$k]->max_length);
+*/
+ if ($info->length !== $fields['meta'][$k]->length)
+ printf("[021 - %d] Expecting length %s/%s got %s/%s\n",
+ $k, gettype($info->length), $info->length, gettype($fields['meta'][$k]->length), $fields['meta'][$k]->length);
+
+ if ($info->charsetnr !== $fields['meta'][$k]->charsetnr)
+ printf("[022 - %d] Expecting charsetnr %s/%s got %s/%s\n",
+ $k, gettype($info->charsetnr), $info->charsetnr, gettype($fields['meta'][$k]->charsetnr), $fields['meta'][$k]->charsetnr);
+
+ if ($info->flags !== $fields['meta'][$k]->flags)
+ printf("[023 - %d] Expecting flags %s/%s got %s/%s\n",
+ $k, gettype($info->flags), $info->flags, gettype($fields['meta'][$k]->flags), $fields['meta'][$k]->flags);
+
+ if ($info->type !== $fields['meta'][$k]->type)
+ printf("[024 - %d] Expecting type %s/%s got %s/%s\n",
+ $k, gettype($info->type), $info->type, gettype($fields['meta'][$k]->type), $fields['meta'][$k]->type);
+
+ if ($info->decimals !== $fields['meta'][$k]->decimals)
+ printf("[025 - %d] Expecting decimals %s/%s got %s/%s\n",
+ $k, getdecimals($info->decimals), $info->decimals, getdecimals($fields['meta'][$k]->decimals), $fields['meta'][$k]->decimals);
+
+ /* Make them equal for the check */
+ $tmp = $fields['all_res'][$k]->max_length;
+ $fields['all_res'][$k]->max_length = $fields['all_meta'][$k]->max_length;
+
+ if ($fields['all_res'][$k] != $fields['all_meta'][$k]) {
+ printf("[026 - %d] fetch_fields() seems to have returned different data, dumping\n", $k);
+ var_dump($fields['all_res'][$k]);
+ var_dump($fields['all_meta'][$k]);
+ }
+ $fields['all_res'][$k]->max_length = $tmp;
+ }
+
+ $num = count($fields['res']);
+ for ($i = 0; $i < 100; $i++) {
+ $pos = mt_rand(-1, $num + 1);
+ if ($pos >= 0 && $pos < $num) {
+ if (true !== mysqli_field_seek($res, $pos))
+ printf("[027] field_seek(res) failed\n");
+ if (true !== $res_meta->field_seek($pos))
+ printf("[028] field_seek(res__meta) failed\n");
+
+ $tmp1 = $res->fetch_field();
+ $tmp2 = mysqli_fetch_field($res_meta);
+ $tmp2->max_length = $tmp1->max_length;
+ if ($tmp1 != $tmp2) {
+ printf("[029] Field info differs, dumping data\n");
+ var_dump($tmp1);
+ var_dump($tmp2);
+ }
+
+ if ($tmp1 != $fields['res'][$pos]) {
+ printf("[030] Field info differs, dumping data\n");
+ var_dump($tmp1);
+ var_dump($fields['res'][$pos]);
+ }
+
+ $pos++;
+ if ($pos !== ($tmp = mysqli_field_tell($res)))
+ printf("[031] Expecting %s/%s got %s/%s\n",
+ gettype($pos), $pos, gettype($tmp), $tmp);
+
+ if ($pos !== ($tmp = mysqli_field_tell($res_meta)))
+ printf("[032] Expecting %s/%s got %s/%s\n",
+ gettype($pos), $pos, gettype($tmp), $tmp);
+ } else {
+
+ if (false !== @mysqli_field_seek($res, $pos))
+ printf("[033] field_seek(%d) did not fail\n", $pos);
+ if (false !== @mysqli_field_seek($res_meta, $pos))
+ printf("[034] field_seek(%d) did not fail\n", $pos);
+ }
+ }
+
+ $res->free_result();
+ mysqli_free_result($res_meta);
+
+ var_dump(mysqli_fetch_field($res));
+
+ mysqli_stmt_close($stmt);
+
+ var_dump(mysqli_fetch_field($res));
+
+ mysqli_close($link);
+
+ var_dump(mysqli_fetch_field($res));
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+array(2) {
+ [%u|b%"id"]=>
+ int(1)
+ [%u|b%"label"]=>
+ %unicode|string%(1) "a"
+}
+NULL
+bool(false)
+bool(false)
+id
+label
+_id
+_label
+_null
+_label_concat
+
+Warning: mysqli_fetch_field(): Couldn't fetch mysqli_result in %s on line %d
+NULL
+
+Warning: mysqli_fetch_field(): Couldn't fetch mysqli_result in %s on line %d
+NULL
+
+Warning: mysqli_fetch_field(): Couldn't fetch mysqli_result in %s on line %d
+NULL
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_get_result_metadata_fetch_field.phpt b/ext/mysqli/tests/mysqli_stmt_get_result_metadata_fetch_field.phpt
new file mode 100644
index 0000000..afaccaf
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_get_result_metadata_fetch_field.phpt
@@ -0,0 +1,176 @@
+--TEST--
+mysqli_stmt_get_result() - meta data, field info
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+if (!function_exists('mysqli_stmt_get_result'))
+ die('skip mysqli_stmt_get_result not available');
+?>
+--FILE--
+<?php
+ require('table.inc');
+ $charsets = my_get_charsets($link);
+
+ if (!($stmt = mysqli_stmt_init($link)) ||
+ !mysqli_stmt_prepare($stmt, "SELECT id, label, id + 1 as _id, concat(label, '_') ___label FROM test ORDER BY id ASC LIMIT 3") ||
+ !mysqli_stmt_execute($stmt))
+ printf("[001] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!is_object($res = mysqli_stmt_get_result($stmt)) || 'mysqli_result' != get_class($res)) {
+ printf("[002] Expecting object/mysqli_result got %s/%s, [%d] %s\n",
+ gettype($res), $res, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ }
+
+ if (!is_object($res_meta = mysqli_stmt_result_metadata($stmt)) ||
+ 'mysqli_result' != get_class($res_meta)) {
+ printf("[003] Expecting object/mysqli_result got %s/%s, [%d] %s\n",
+ gettype($res), $res, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ }
+
+ $i = 0;
+ while ($field = $res->fetch_field()) {
+ var_dump($field);
+ $i++;
+ if (2 == $i) {
+ /*
+ Label column, result set charset.
+ All of the following columns are "too hot" - too server dependent
+ */
+ if ($field->charsetnr != $charsets['results']['nr']) {
+ printf("[004] Expecting charset %s/%d got %d\n",
+ $charsets['results']['charset'],
+ $charsets['results']['nr'], $field->charsetnr);
+ }
+ if ($field->length != (1 * $charsets['results']['maxlen'])) {
+ printf("[005] Expecting length %d got %d\n",
+ $charsets['results']['maxlen'],
+ $field->max_length);
+ }
+ }
+ }
+
+ mysqli_stmt_close($stmt);
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+object(stdClass)#%d (13) {
+ [%u|b%"name"]=>
+ %unicode|string%(2) "id"
+ [%u|b%"orgname"]=>
+ %unicode|string%(2) "id"
+ [%u|b%"table"]=>
+ %unicode|string%(4) "test"
+ [%u|b%"orgtable"]=>
+ %unicode|string%(4) "test"
+ [%u|b%"def"]=>
+ %unicode|string%(0) ""
+ [%u|b%"db"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"catalog"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"max_length"]=>
+ int(0)
+ [%u|b%"length"]=>
+ int(11)
+ [%u|b%"charsetnr"]=>
+ int(63)
+ [%u|b%"flags"]=>
+ int(49155)
+ [%u|b%"type"]=>
+ int(3)
+ [%u|b%"decimals"]=>
+ int(0)
+}
+object(stdClass)#%d (13) {
+ [%u|b%"name"]=>
+ %unicode|string%(5) "label"
+ [%u|b%"orgname"]=>
+ %unicode|string%(5) "label"
+ [%u|b%"table"]=>
+ %unicode|string%(4) "test"
+ [%u|b%"orgtable"]=>
+ %unicode|string%(4) "test"
+ [%u|b%"def"]=>
+ %unicode|string%(0) ""
+ [%u|b%"db"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"catalog"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"max_length"]=>
+ int(%d)
+ [%u|b%"length"]=>
+ int(%d)
+ [%u|b%"charsetnr"]=>
+ int(%d)
+ [%u|b%"flags"]=>
+ int(0)
+ [%u|b%"type"]=>
+ int(254)
+ [%u|b%"decimals"]=>
+ int(0)
+}
+object(stdClass)#%d (13) {
+ [%u|b%"name"]=>
+ %unicode|string%(3) "_id"
+ [%u|b%"orgname"]=>
+ %unicode|string%(0) ""
+ [%u|b%"table"]=>
+ %unicode|string%(0) ""
+ [%u|b%"orgtable"]=>
+ %unicode|string%(0) ""
+ [%u|b%"def"]=>
+ %unicode|string%(0) ""
+ [%u|b%"db"]=>
+ %unicode|string%(0) ""
+ [%u|b%"catalog"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"max_length"]=>
+ int(0)
+ [%u|b%"length"]=>
+ int(%d)
+ [%u|b%"charsetnr"]=>
+ int(63)
+ [%u|b%"flags"]=>
+ int(32897)
+ [%u|b%"type"]=>
+ int(8)
+ [%u|b%"decimals"]=>
+ int(0)
+}
+object(stdClass)#%d (13) {
+ [%u|b%"name"]=>
+ %unicode|string%(8) "___label"
+ [%u|b%"orgname"]=>
+ %unicode|string%(0) ""
+ [%u|b%"table"]=>
+ %unicode|string%(0) ""
+ [%u|b%"orgtable"]=>
+ %unicode|string%(0) ""
+ [%u|b%"def"]=>
+ %unicode|string%(0) ""
+ [%u|b%"db"]=>
+ %unicode|string%(0) ""
+ [%u|b%"catalog"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"max_length"]=>
+ int(%d)
+ [%u|b%"length"]=>
+ int(%d)
+ [%u|b%"charsetnr"]=>
+ int(%d)
+ [%u|b%"flags"]=>
+ int(0)
+ [%u|b%"type"]=>
+ int(253)
+ [%u|b%"decimals"]=>
+ int(31)
+}
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_get_result_non_select.phpt b/ext/mysqli/tests/mysqli_stmt_get_result_non_select.phpt
new file mode 100644
index 0000000..c057f7d
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_get_result_non_select.phpt
@@ -0,0 +1,95 @@
+--TEST--
+mysqli_stmt_get_result() - SHOW, DESCRIBE, EXPLAIN
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+if (!function_exists('mysqli_stmt_get_result'))
+ die('skip mysqli_stmt_get_result not available');
+?>
+--FILE--
+<?php
+ /*
+ NOTE: no datatype tests here! This is done by
+ mysqli_stmt_bind_result.phpt already. Restrict
+ this test case to the basics.
+ */
+ require('table.inc');
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[001] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (mysqli_query($link, 'PREPARE mystmt FROM "SHOW ENGINES"')) {
+ mysqli_query($link, 'DEALLOCATE PREPARE mystmt');
+
+ if (!$stmt->prepare('SHOW ENGINES') ||
+ !$stmt->execute())
+ printf("[002] [%d] %s\n", $stmt->errno, $stmt->error);
+
+ if (!$res = $stmt->get_result())
+ printf("[003] [%d] %s\n", $stmt->errno, $stmt->error);
+
+ $engines = mysqli_fetch_all($res, MYSQLI_NUM);
+ if (empty($engines)) {
+ printf("[004] It is very unlikely that SHOW ENGINES returns no data, check manually\n");
+ } else {
+ $found = false;
+ foreach ($engines as $k => $engine)
+ foreach ($engine as $k => $v)
+ if (stristr('MyISAM', $v)) {
+ $found = true;
+ break;
+ }
+ if (!$found)
+ printf("[005] It is very unlikely that SHOW ENGINES does not show MyISAM, check manually\n");
+ }
+ mysqli_free_result($res);
+ }
+
+ if (mysqli_query($link, 'PREPARE mystmt FROM "DESCRIBE test id"')) {
+ mysqli_query($link, 'DEALLOCATE PREPARE mystmt');
+
+ if (!$stmt->prepare('DESCRIBE test id') ||
+ !$stmt->execute())
+ printf("[006] [%d] %s\n", $stmt->errno, $stmt->error);
+
+ if (!$res = $stmt->get_result())
+ printf("[007] [%d] %s\n", $stmt->errno, $stmt->error);
+
+ $description = mysqli_fetch_assoc($res);
+ if ($description['Field'] != 'id') {
+ printf("[008] Returned data seems wrong, [%d] %s\n",
+ mysqli_errno($link), mysqli_error($link));
+ var_dump($description);
+ }
+ mysqli_free_result($res);
+ }
+
+ if (mysqli_query($link, 'PREPARE mystmt FROM "EXPLAIN SELECT id FROM test"')) {
+ mysqli_query($link, 'DEALLOCATE PREPARE mystmt');
+
+ if (!$stmt->prepare('EXPLAIN SELECT id FROM test') ||
+ !$stmt->execute())
+ printf("[009] [%d] %s\n", $stmt->errno, $stmt->error);
+
+ if (!$res = $stmt->get_result())
+ printf("[010] [%d] %s\n", $stmt->errno, $stmt->error);
+
+ $tmp = mysqli_fetch_assoc($res);
+ if (empty($tmp))
+ printf("[011] Empty EXPLAIN result set seems wrong, check manually, [%d] %s\n",
+ mysqli_errno($link), mysqli_error($link));
+ mysqli_free_result($res);
+ }
+ mysqli_close($link);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_get_result_seek.phpt b/ext/mysqli/tests/mysqli_stmt_get_result_seek.phpt
new file mode 100644
index 0000000..ffb655d
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_get_result_seek.phpt
@@ -0,0 +1,129 @@
+--TEST--
+mysqli_stmt_get_result() - seeking
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+if (!function_exists('mysqli_stmt_get_result'))
+ die('skip mysqli_stmt_get_result not available');
+?>
+--FILE--
+<?php
+ require('table.inc');
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[001] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_stmt_prepare($stmt, "SELECT id, label FROM test ORDER BY id ASC LIMIT 3"))
+ printf("[002] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_execute($stmt))
+ printf("[003] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!is_object($res = mysqli_stmt_get_result($stmt)) || 'mysqli_result' != get_class($res)) {
+ printf("[004] Expecting object/mysqli_result got %s/%s, [%d] %s\n",
+ gettype($res), $res, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ }
+
+ if (3 !== $res->num_rows)
+ printf("[005] Expecting 3 rows, got %s/%s rows\n", gettype($res->num_rows), $res->num_rows);
+
+ if (2 !== $res->field_count)
+ printf("[006] Expecting 2 fields, got %s/%s rows\n", gettype($res->field_count), $res->field_count);
+
+ if (0 !== $res->current_field)
+ printf("[006] Expecting offset 0, got %s/%s rows\n", gettype($res->current_field), $res->current_field);
+
+ for ($i = 2; $i > 0; $i--) {
+ if (!$res->data_seek($i))
+ printf("[007] Cannot seek to position %d, [%d] %s\n",
+ $i, mysqli_stmt_errno($stmt), $stmt->error);
+ $row = $res->fetch_array(MYSQLI_BOTH);
+ if (($row[0] !== $row['id']) || ($row[0] !== $i + 1)) {
+ printf("[008] Record looks wrong, dumping data\n");
+ var_dump($row);
+ } else {
+ unset($row[0]);
+ unset($row['id']);
+ }
+ if ($row[1] !== $row['label']) {
+ printf("[009] Record looks wrong, dumping data\n");
+ var_dump($row);
+ } else {
+ unset($row[1]);
+ unset($row['label']);
+ }
+ if (!empty($row)) {
+ printf("[010] Not empty, dumping unexpected data\n");
+ var_dump($row);
+ }
+ }
+
+ if (false !== ($tmp = $res->data_seek(-1)))
+ printf("[011] Expecting boolean/false got %s/%s\n", gettype($tmp), $tmp);
+
+ if (false !== ($tmp = $res->data_seek($res->num_rows + 1)))
+ printf("[012] Expecting boolean/false got %s/%s\n", gettype($tmp), $tmp);
+
+ if (false !== ($tmp = $res->data_seek(PHP_INT_MAX + 1)))
+ printf("[013] Expecting boolean/false got %s/%s\n", gettype($tmp), $tmp);
+
+ for ($i = 0; $i < 100; $i++) {
+ /* intentionally out of range! */
+ $pos = mt_rand(-1, 4);
+ $tmp = mysqli_data_seek($res, $pos);
+ if (($pos >= 0 && $pos < 3)) {
+ if (true !== $tmp)
+ printf("[015] Expecting boolan/true got %s/%s\n", gettype($tmp), $tmp);
+ $row = $res->fetch_array(MYSQLI_NUM);
+ if ($row[0] !== $pos + 1)
+ printf("[016] Expecting id = %d for pos %d got %s/%s\n",
+ $pos + 1, $pos, gettype($row[0]), $row[0]);
+ } else {
+ if (false !== $tmp)
+ printf("[014] Expecting boolan/false got %s/%s\n", gettype($tmp), $tmp);
+ }
+ }
+
+ mysqli_stmt_close($stmt);
+
+ if (true !== ($tmp = mysqli_data_seek($res, 0)))
+ printf("[015] Expecting boolan/true got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_array($row = $res->fetch_array(MYSQLI_NUM)))
+ printf("[016] Expecting array got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_free_result($res);
+
+ if (NULL !== ($tmp = mysqli_data_seek($res, 0)))
+ printf("[017] Expecting NULL got %s/%s\n", gettype($tmp), $tmp);
+
+ if (NULL !== ($row = $res->fetch_array(MYSQLI_NUM)))
+ printf("[018] Expecting NULL got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_close($link);
+
+ if (NULL !== ($tmp = mysqli_data_seek($res, 0)))
+ printf("[019] Expecting NULL got %s/%s\n", gettype($tmp), $tmp);
+
+ if (NULL !== ($row = $res->fetch_array(MYSQLI_NUM)))
+ printf("[020] Expecting NULL got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+
+Warning: mysqli_data_seek(): Couldn't fetch mysqli_result in %s on line %d
+
+Warning: mysqli_result::fetch_array(): Couldn't fetch mysqli_result in %s on line %d
+
+Warning: mysqli_data_seek(): Couldn't fetch mysqli_result in %s on line %d
+
+Warning: mysqli_result::fetch_array(): Couldn't fetch mysqli_result in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_get_result_types.phpt b/ext/mysqli/tests/mysqli_stmt_get_result_types.phpt
new file mode 100644
index 0000000..724a32a
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_get_result_types.phpt
@@ -0,0 +1,259 @@
+--TEST--
+mysqli_stmt_get_result - data types
+--SKIPIF--
+<?php
+ require_once('skipif.inc');
+ require_once('skipifemb.inc');
+ require_once('skipifconnectfailure.inc');
+
+ if (!function_exists('mysqli_stmt_get_result'))
+ die("skip mysqli_stmt_get_result() not available");
+?>
+--FILE--
+<?php
+ require('connect.inc');
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+ $hint_str_or_unicode = (version_compare(PHP_VERSION, '5.9.9', '>') == 1) ? 'unicode' : 'string';
+
+ function func_mysqli_stmt_get_result($link, $engine, $bind_type, $sql_type, $bind_value, $offset, $type_hint = null) {
+
+ if (!mysqli_query($link, "DROP TABLE IF EXISTS test")) {
+ printf("[%04d] [%d] %s\n", $offset, mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ if (!mysqli_query($link, sprintf("CREATE TABLE test(id INT, label %s, PRIMARY KEY(id)) ENGINE = %s", $sql_type, $engine))) {
+ // don't bail - column type might not be supported by the server, ignore this
+ return false;
+ }
+
+ if (!$stmt = mysqli_stmt_init($link)) {
+ printf("[%04d] [%d] %s\n", $offset + 1, mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ if (!mysqli_stmt_prepare($stmt, "INSERT INTO test(id, label) VALUES (?, ?)")) {
+ printf("[%04d] [%d] %s\n", $offset + 2, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ return false;
+ }
+
+ $id = null;
+ if (!mysqli_stmt_bind_param($stmt, "i" . $bind_type, $id, $bind_value)) {
+ printf("[%04d] [%d] %s\n", $offset + 3, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ mysqli_stmt_close($stmt);
+ return false;
+ }
+
+ for ($id = 1; $id < 4; $id++) {
+ if (!mysqli_stmt_execute($stmt)) {
+ printf("[%04d] [%d] %s\n", $offset + 3 + $id, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ mysqli_stmt_close($stmt);
+ return false;
+ }
+ }
+ mysqli_stmt_close($stmt);
+
+ $stmt = mysqli_stmt_init($link);
+
+ if (!mysqli_stmt_prepare($stmt, "SELECT id, label FROM test")) {
+ printf("[%04d] [%d] %s\n", $offset + 7, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ mysqli_stmt_close($stmt);
+ return false;
+ }
+
+ if (!mysqli_stmt_execute($stmt)) {
+ printf("[%04d] [%d] %s\n", $offset + 8, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ mysqli_stmt_close($stmt);
+ return false;
+ }
+
+ $result = mysqli_stmt_result_metadata($stmt);
+
+ if (!$res = mysqli_stmt_get_result($stmt)) {
+ printf("[%04d] [%d] %s\n", $offset + 9, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ mysqli_stmt_close($stmt);
+ return false;
+ }
+ $num = 0;
+ $fields = mysqli_fetch_fields($result);
+
+ while ($row = mysqli_fetch_assoc($res)) {
+ $bind_res = &$row['label'];
+ if (!gettype($bind_res) == 'unicode') {
+ if ($bind_res !== $bind_value && (!$type_hint || ($type_hint !== gettype($bind_res)))) {
+ printf("[%04d] [%d] Expecting %s/'%s' [type hint = %s], got %s/'%s'\n",
+ $offset + 10, $num,
+ gettype($bind_value), $bind_value, $type_hint,
+ gettype($bind_res), $bind_res);
+ mysqli_free_result($res);
+ mysqli_stmt_close($stmt);
+ return false;
+ }
+ }
+ $num++;
+ }
+
+ if ($num != 3) {
+ printf("[%04d] [%d] %s, expecting 3 results, got only %d results\n",
+ $offset + 11, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt), $num);
+ mysqli_free_result($res);
+ mysqli_stmt_close($stmt);
+ return false;
+ }
+
+ mysqli_free_result($res);
+ mysqli_stmt_close($stmt);
+ return true;
+ }
+
+
+ function func_mysqli_stmt_bind_make_string($len) {
+
+ $ret = '';
+ for ($i = 0; $i < $len; $i++)
+ $ret .= chr(mt_rand(65, 90));
+
+ return $ret;
+ }
+
+ func_mysqli_stmt_get_result($link, $engine, "i", "TINYINT", -11, 20);
+ func_mysqli_stmt_get_result($link, $engine, "i", "TINYINT", NULL, 40);
+ func_mysqli_stmt_get_result($link, $engine, "i", "TINYINT UNSIGNED", 1, 60);
+ func_mysqli_stmt_get_result($link, $engine, "i", "TINYINT UNSIGNED", NULL, 80);
+
+ func_mysqli_stmt_get_result($link, $engine, "i", "BOOL", 1, 100);
+ func_mysqli_stmt_get_result($link, $engine, "i", "BOOL", NULL, 120);
+ func_mysqli_stmt_get_result($link, $engine, "i", "BOOLEAN", 0, 140);
+ func_mysqli_stmt_get_result($link, $engine, "i", "BOOLEAN", NULL, 160);
+
+ func_mysqli_stmt_get_result($link, $engine, "i", "SMALLINT", -32768, 180);
+ func_mysqli_stmt_get_result($link, $engine, "i", "SMALLINT", 32767, 200);
+ func_mysqli_stmt_get_result($link, $engine, "i", "SMALLINT", NULL, 220);
+ func_mysqli_stmt_get_result($link, $engine, "i", "SMALLINT UNSIGNED", 65535, 240);
+ func_mysqli_stmt_get_result($link, $engine, "i", "SMALLINT UNSIGNED", NULL, 260);
+
+ func_mysqli_stmt_get_result($link, $engine, "d", "MEDIUMINT", -8388608, 280, "integer");
+ func_mysqli_stmt_get_result($link, $engine, "d", "MEDIUMINT", 8388607, 300, "integer");
+ func_mysqli_stmt_get_result($link, $engine, "d", "MEDIUMINT", NULL, 320);
+ func_mysqli_stmt_get_result($link, $engine, "d", "MEDIUMINT UNSIGNED", 16777215, 340, "integer");
+ func_mysqli_stmt_get_result($link, $engine, "d", "MEDIUMINT UNSIGNED", NULL, 360);
+
+ func_mysqli_stmt_get_result($link, $engine, "i", "INTEGER", (defined("PHP_INT_MAX")) ? max(-1 * PHP_INT_MAX + 1, -2147483648) : 1, 380);
+ func_mysqli_stmt_get_result($link, $engine, "i", "INTEGER", -2147483647, 400, "integer");
+ func_mysqli_stmt_get_result($link, $engine, "i", "INTEGER", (defined("PHP_INT_MAX")) ? min(2147483647, PHP_INT_MAX) : 1, 420);
+ func_mysqli_stmt_get_result($link, $engine, "i", "INTEGER", NULL, 440);
+ func_mysqli_stmt_get_result($link, $engine, "i", "INTEGER UNSIGNED", (defined("PHP_INT_MAX")) ? min(4294967295, 2147483647) : 1, 460);
+ func_mysqli_stmt_get_result($link, $engine, "i", "INTEGER UNSIGNED", 4294967295, 480, (defined("PHP_INT_MAX") && (4294967295 > PHP_INT_MAX)) ? "string" : null);
+ func_mysqli_stmt_get_result($link, $engine, "i", "INTEGER UNSIGNED", NULL, 500);
+
+ /* test is broken too: we bind "integer" but value is a float
+ func_mysqli_stmt_get_result($link, $engine, "i", "BIGINT", -9223372036854775808, 520);
+ func_mysqli_stmt_get_result($link, $engine, "i", "BIGINT UNSIGNED", 18446744073709551615, 560);
+ */
+ func_mysqli_stmt_get_result($link, $engine, "i", "BIGINT", NULL, 540);
+ func_mysqli_stmt_get_result($link, $engine, "i", "BIGINT UNSIGNED", NULL, 580);
+ func_mysqli_stmt_get_result($link, $engine, "i", "BIGINT", -1, 1780);
+ func_mysqli_stmt_get_result($link, $engine, "i", "BIGINT UNSIGNED", 1, 1800);
+ func_mysqli_stmt_get_result($link, $engine, "i", "BIGINT", -1 * PHP_INT_MAX + 1, 1820);
+ func_mysqli_stmt_get_result($link, $engine, "i", "BIGINT UNSIGNED", PHP_INT_MAX, 1840);
+ func_mysqli_stmt_get_result($link, $engine, "s", "BIGINT UNSIGNED", "18446744073709551615", 1860);
+ func_mysqli_stmt_get_result($link, $engine, "s", "BIGINT", "-9223372036854775808", 1880);
+
+ func_mysqli_stmt_get_result($link, $engine, "d", "FLOAT", -9223372036854775808 - 1.1, 600);
+ func_mysqli_stmt_get_result($link, $engine, "d", "FLOAT", NULL, 620);
+ func_mysqli_stmt_get_result($link, $engine, "d", "FLOAT UNSIGNED", 18446744073709551615 + 1.1, 640);
+ func_mysqli_stmt_get_result($link, $engine, "d", "FLOAT UNSIGNED ", NULL, 660);
+
+ // Yes, we need the temporary variable. The PHP casting will fouls us otherwise.
+ $tmp = strval('-99999999.99');
+ func_mysqli_stmt_get_result($link, $engine, "d", "DOUBLE(10,2)", $tmp, 680, "string");
+ func_mysqli_stmt_get_result($link, $engine, "d", "DOUBLE(10,2)", NULL, 700);
+ $tmp = strval('99999999.99');
+ func_mysqli_stmt_get_result($link, $engine, "d", "DOUBLE(10,2) UNSIGNED", $tmp , 720, "string");
+ func_mysqli_stmt_get_result($link, $engine, "d", "DOUBLE(10,2) UNSIGNED", NULL, 740);
+ $tmp = strval('-99999999.99');
+ func_mysqli_stmt_get_result($link, $engine, "d", "DECIMAL(10,2)", $tmp, 760, "string");
+ func_mysqli_stmt_get_result($link, $engine, "d", "DECIMAL(10,2)", NULL, 780);
+ $tmp = strval('99999999.99');
+ func_mysqli_stmt_get_result($link, $engine, "d", "DECIMAL(10,2)", $tmp, 800, "string");
+ func_mysqli_stmt_get_result($link, $engine, "d", "DECIMAL(10,2)", NULL, 820);
+
+ // don't care about date() strict TZ warnings...
+ func_mysqli_stmt_get_result($link, $engine, "s", "DATE", @date('Y-m-d'), 840);
+ func_mysqli_stmt_get_result($link, $engine, "s", "DATE NOT NULL", @date('Y-m-d'), 860);
+ func_mysqli_stmt_get_result($link, $engine, "s", "DATE", NULL, 880);
+
+ func_mysqli_stmt_get_result($link, $engine, "s", "DATETIME", @date('Y-m-d H:i:s'), 900);
+ func_mysqli_stmt_get_result($link, $engine, "s", "DATETIME NOT NULL", @date('Y-m-d H:i:s'), 920);
+ func_mysqli_stmt_get_result($link, $engine, "s", "DATETIME", NULL, 940);
+
+ func_mysqli_stmt_get_result($link, $engine, "s", "TIMESTAMP", @date('Y-m-d H:i:s'), 960);
+
+ func_mysqli_stmt_get_result($link, $engine, "s", "TIME", @date('H:i:s'), 980);
+ func_mysqli_stmt_get_result($link, $engine, "s", "TIME NOT NULL", @date('H:i:s'), 1000);
+ func_mysqli_stmt_get_result($link, $engine, "s", "TIME", NULL, 1020);
+
+ $tmp = intval(@date('Y'));
+ func_mysqli_stmt_get_result($link, $engine, "s", "YEAR", $tmp, 1040, "integer");
+ func_mysqli_stmt_get_result($link, $engine, "s", "YEAR NOT NULL", $tmp, 1060, "integer");
+ func_mysqli_stmt_get_result($link, $engine, "s", "YEAR", NULL, 1080);
+
+ $string255 = func_mysqli_stmt_bind_make_string(255);
+ func_mysqli_stmt_get_result($link, $engine, "s", "CHAR(1)", "a", 1110, $hint_str_or_unicode);
+ func_mysqli_stmt_get_result($link, $engine, "s", "CHAR(255)", $string255, 1120, $hint_str_or_unicode);
+ func_mysqli_stmt_get_result($link, $engine, "s", "CHAR(1) NOT NULL", "a", 1140, $hint_str_or_unicode);
+ func_mysqli_stmt_get_result($link, $engine, "s", "CHAR(1)", NULL, 1160);
+
+ $string65k = func_mysqli_stmt_bind_make_string(65535);
+ func_mysqli_stmt_get_result($link, $engine, "s", "VARCHAR(1)", "a", 1180, $hint_str_or_unicode);
+ func_mysqli_stmt_get_result($link, $engine, "s", "VARCHAR(255)", $string255, 1200, $hint_str_or_unicode);
+ func_mysqli_stmt_get_result($link, $engine, "s", "VARCHAR(65635)", $string65k, 1220, $hint_str_or_unicode);
+ func_mysqli_stmt_get_result($link, $engine, "s", "VARCHAR(1) NOT NULL", "a", 1240, $hint_str_or_unicode);
+ func_mysqli_stmt_get_result($link, $engine, "s", "VARCHAR(1)", NULL, 1260);
+
+ func_mysqli_stmt_get_result($link, $engine, "s", "BINARY(1)", "a", 1280);
+ func_mysqli_stmt_get_result($link, $engine, "s", "BINARY(1)", chr(0), 1300);
+ func_mysqli_stmt_get_result($link, $engine, "s", "BINARY(1) NOT NULL", "b", 1320);
+ func_mysqli_stmt_get_result($link, $engine, "s", "BINARY(1)", NULL, 1340);
+
+ func_mysqli_stmt_get_result($link, $engine, "s", "VARBINARY(1)", "a", 1360);
+ func_mysqli_stmt_get_result($link, $engine, "s", "VARBINARY(1)", chr(0), 1380);
+ func_mysqli_stmt_get_result($link, $engine, "s", "VARBINARY(1) NOT NULL", "b", 1400);
+ func_mysqli_stmt_get_result($link, $engine, "s", "VARBINARY(1)", NULL, 1420);
+
+ func_mysqli_stmt_get_result($link, $engine, "s", "TINYBLOB", "a", 1440);
+ func_mysqli_stmt_get_result($link, $engine, "s", "TINYBLOB", chr(0), 1460);
+ func_mysqli_stmt_get_result($link, $engine, "s", "TINYBLOB NOT NULL", "b", 1480);
+ func_mysqli_stmt_get_result($link, $engine, "s", "TINYBLOB", NULL, 1500);
+
+ func_mysqli_stmt_get_result($link, $engine, "s", "TINYTEXT", "a", 1520, $hint_str_or_unicode);
+ func_mysqli_stmt_get_result($link, $engine, "s", "TINYTEXT NOT NULL", "a", 1540, $hint_str_or_unicode);
+ func_mysqli_stmt_get_result($link, $engine, "s", "TINYTEXT", NULL, 1560, $hint_str_or_unicode);
+
+ // Note: you cannot insert any blob values this way. But you can check the API at least partly this way
+ // Extra BLOB tests are in mysqli_stmt_send_long()
+ func_mysqli_stmt_get_result($link, $engine, "b", "BLOB", b"", 1580);
+ func_mysqli_stmt_get_result($link, $engine, "b", "TEXT", "", 1600, $hint_str_or_unicode);
+ func_mysqli_stmt_get_result($link, $engine, "b", "MEDIUMBLOB", b"", 1620);
+ func_mysqli_stmt_get_result($link, $engine, "b", "MEDIUMTEXT", "", 1640, $hint_str_or_unicode);
+
+ /* Is this one related? http://bugs.php.net/bug.php?id=35759 */
+ func_mysqli_stmt_get_result($link, $engine, "b", "LONGBLOB", "", 1660);
+ func_mysqli_stmt_get_result($link, $engine, "b", "LONGTEXT", "", 1680, $hint_str_or_unicode);
+
+ func_mysqli_stmt_get_result($link, $engine, "s", "ENUM('a', 'b')", "a", 1700, $hint_str_or_unicode);
+ func_mysqli_stmt_get_result($link, $engine, "s", "ENUM('a', 'b')", NULL, 1720, $hint_str_or_unicode);
+ func_mysqli_stmt_get_result($link, $engine, "s", "SET('a', 'b')", "a", 1740, $hint_str_or_unicode);
+ func_mysqli_stmt_get_result($link, $engine, "s", "SET('a', 'b')", NULL, 1760, $hint_str_or_unicode);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_get_warnings.phpt b/ext/mysqli/tests/mysqli_stmt_get_warnings.phpt
new file mode 100644
index 0000000..2b0e150
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_get_warnings.phpt
@@ -0,0 +1,107 @@
+--TEST--
+mysqli_stmt_get_warnings() - TODO
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+require_once("connect.inc");
+
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ die(sprintf("skip Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket));
+}
+
+if (!mysqli_query($link, "DROP TABLE IF EXISTS test") ||
+ !mysqli_query($link, "CREATE TABLE test(id SMALLINT)"))
+ die(sprintf("skip [%d] %s\n", $link->errno, $link->error));
+
+if (!@mysqli_query("INSERT INTO test(id) VALUES (100001)"))
+ die("skip Strict sql mode seems to be active. We won't get a warning to check for.");
+
+mysqli_query($link, "DROP TABLE IF EXISTS test");
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_stmt_get_warnings()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_get_warnings($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (NULL !== ($tmp = mysqli_stmt_get_warnings($stmt)))
+ printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_prepare($stmt, "DROP TABLE IF EXISTS test") || !mysqli_stmt_execute($stmt))
+ printf("[005] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (false !== ($tmp = mysqli_stmt_get_warnings($stmt)))
+ printf("[006] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_prepare($stmt, "CREATE TABLE test(id SMALLINT, label CHAR(1))") || !mysqli_stmt_execute($stmt))
+ printf("[007] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (false !== ($tmp = mysqli_stmt_get_warnings($stmt)))
+ printf("[008] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_prepare($stmt, "INSERT INTO test(id, label) VALUES (100000, 'a'), (100001, 'b')") ||
+ !mysqli_stmt_execute($stmt))
+ printf("[009] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!is_object($warning = mysqli_stmt_get_warnings($stmt)))
+ printf("[010] Expecting mysqli_warning object, got %s/%s\n", gettype($warning), $warning);
+
+ if ('mysqli_warning' !== get_class($warning))
+ printf("[011] Expecting object of type mysqli_warning got type '%s'", get_class($warning));
+
+ if (!method_exists($warning, 'next'))
+ printf("[012] Object mysqli_warning seems to lack method next()\n");
+
+ $i = 0;
+ do {
+
+ if ('' == $warning->message)
+ printf("[013 - %d] Message should not be empty\n", $i);
+
+ if ('' == $warning->sqlstate)
+ printf("[014 - %d] SQL State should not be empty\n", $i);
+
+ if (0 == $warning->errno)
+ printf("[015 - %d] Error number should not be zero\n", $i);
+
+ $i++;
+
+ } while ($warning->next());
+
+ if (2 != $i)
+ printf("[016] Expected 2 warnings, got %d warnings\n", $i);
+
+ mysqli_stmt_close($stmt);
+
+ if (NULL !== ($tmp = mysqli_stmt_get_warnings($stmt)))
+ printf("[015] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Warning: mysqli_stmt_get_warnings(): invalid object or resource mysqli_stmt
+ in %s on line %d
+
+Warning: mysqli_stmt_get_warnings(): Couldn't fetch mysqli_stmt in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_init.phpt b/ext/mysqli/tests/mysqli_stmt_init.phpt
new file mode 100644
index 0000000..4f09719
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_init.phpt
@@ -0,0 +1,58 @@
+--TEST--
+mysqli_stmt_init()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ /*
+ NOTE: no datatype tests here! This is done by
+ mysqli_stmt_bind_result.phpt already. Restrict
+ this test case to the basics.
+ */
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_stmt_init()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_init($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (!is_object($stmt = mysqli_stmt_init($link)))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!is_object($stmt2 = @mysqli_stmt_init($link)))
+ printf("[003a] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ mysqli_stmt_close($stmt);
+
+ if (NULL !== ($tmp = mysqli_stmt_init($stmt)))
+ printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_close($link);
+
+ if (NULL !== ($tmp = mysqli_stmt_init($link)))
+ printf("[005] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Warning: mysqli_stmt_close(): invalid object or resource mysqli_stmt
+ in %s on line %d
+
+Warning: mysqli_stmt_init() expects parameter 1 to be mysqli, object given in %s on line %d
+
+Warning: mysqli_stmt_init(): Couldn't fetch mysqli in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_insert_id.phpt b/ext/mysqli/tests/mysqli_stmt_insert_id.phpt
new file mode 100644
index 0000000..c7a5aff
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_insert_id.phpt
@@ -0,0 +1,77 @@
+--TEST--
+mysqli_stmt_insert_id()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_stmt_insert_id()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ $stmt = @new mysqli_stmt($link);
+ if (!is_null($tmp = @mysqli_insert_id($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ $stmt = mysqli_stmt_init($link);
+ if (NULL !== ($tmp = @mysqli_stmt_insert_id($stmt)))
+ printf("[003] Expecting NULL/NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_prepare($stmt, "SELECT id, label FROM test ORDER BY id LIMIT 1") ||
+ !mysqli_stmt_execute($stmt)) {
+ printf("[004] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ }
+
+ if (0 !== ($tmp = mysqli_stmt_insert_id($stmt)))
+ printf("[005] Expecting int/0, got %s/%s\n", gettype($tmp), $tmp);
+ mysqli_stmt_close($stmt);
+
+ // no auto_increment column
+ $stmt = mysqli_stmt_init($link);
+ if (!mysqli_stmt_prepare($stmt, "INSERT INTO test(id, label) VALUES (100, 'a')") ||
+ !mysqli_stmt_execute($stmt)) {
+ printf("[006] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ }
+
+ if (0 !== ($tmp = mysqli_stmt_insert_id($stmt)))
+ printf("[007] Expecting int/0, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (mysqli_get_server_version($link) > 50000 &&
+ (!mysqli_stmt_prepare($stmt, "ALTER TABLE test MODIFY id INT NOT NULL AUTO_INCREMENT") ||
+ !mysqli_stmt_execute($stmt))) {
+ printf("[008] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ } else if (mysqli_get_server_version($link) < 50000){
+ mysqli_query($link, "ALTER TABLE test MODIFY id INT NOT NULL AUTO_INCREMENT");
+ }
+
+ if (!mysqli_stmt_prepare($stmt, "INSERT INTO test(label) VALUES ('a')") ||
+ !mysqli_stmt_execute($stmt)) {
+ printf("[009] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ }
+ if (0 === ($tmp = mysqli_stmt_insert_id($stmt)))
+ printf("[010] Expecting int/any non zero, got %s/%s\n", gettype($tmp), $tmp);
+ mysqli_stmt_close($stmt);
+
+ mysqli_close($link);
+
+ var_dump(mysqli_stmt_insert_id($stmt));
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Warning: mysqli_stmt_insert_id(): Couldn't fetch mysqli_stmt in %s on line %d
+NULL
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_num_rows.phpt b/ext/mysqli/tests/mysqli_stmt_num_rows.phpt
new file mode 100644
index 0000000..a1f5e89
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_num_rows.phpt
@@ -0,0 +1,118 @@
+--TEST--
+mysqli_stmt_num_rows()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_stmt_num_rows()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_num_rows($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ function func_test_mysqli_stmt_num_rows($stmt, $query, $expected, $offset) {
+
+ if (!mysqli_stmt_prepare($stmt, $query)) {
+ printf("[%03d] [%d] %s\n", $offset, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ return false;
+ }
+
+ if (!mysqli_stmt_execute($stmt)) {
+ printf("[%03d] [%d] %s\n", $offset + 1, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ return false;
+ }
+
+ if (!mysqli_stmt_store_result($stmt)) {
+ printf("[%03d] [%d] %s\n", $offset + 2, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ return false;
+ }
+
+ if ($expected !== ($tmp = mysqli_stmt_num_rows($stmt)))
+ printf("[%03d] Expecting %s/%d, got %s/%d\n", $offset + 3,
+ gettype($expected), $expected,
+ gettype($tmp), $tmp);
+
+ mysqli_stmt_free_result($stmt);
+
+ return true;
+ }
+
+ func_test_mysqli_stmt_num_rows($stmt, "SELECT 1 AS a", 1, 10);
+ func_test_mysqli_stmt_num_rows($stmt, "SHOW VARIABLES LIKE '%nixnutz%'", 0, 20);
+ // Note: for statements that return no result set mysqli_num_rows() differs from mysqli_stmt_num_rows() slightly
+ // mysqli_num_rows() failed to fetch the result set and the PHP parameter check makes it return NULL
+ // mysqli_stmt_numrows() has a valid resource to work on and it will return int/0 instead. No bug, but
+ // slightly different behaviour... - if you really check the data types and don't rely on casting like 98% of all PHP
+ // users do.
+ func_test_mysqli_stmt_num_rows($stmt, "INSERT INTO test(id, label) VALUES (100, 'z')", 0, 30);
+
+ if ($res = mysqli_query($link, 'SELECT COUNT(id) AS num FROM test')) {
+ $row = mysqli_fetch_assoc($res);
+ mysqli_free_result($res);
+ func_test_mysqli_stmt_num_rows($stmt, "SELECT id, label FROM test", (int)$row['num'], 40);
+ } else {
+ printf("[050] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ print "run_tests.php don't fool me with your 'ungreedy' expression '.+?'!\n";
+
+ if (!mysqli_stmt_prepare($stmt, 'SELECT id FROM test'))
+ printf("[051] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (mysqli_stmt_execute($stmt)) {
+
+ $i = 0;
+ do {
+ if (0 !== ($tmp = mysqli_stmt_num_rows($stmt)))
+ printf("[53 - %03d] Expecting int/0, got %s/%s\n", $i, gettype($tmp), $tmp);
+ $i++;
+ } while (mysqli_stmt_fetch($stmt));
+
+ /* NOTE to users
+ Behaviour with libmysql is UNDEFINED, see http://news.php.net/php.internals/55210
+ Because it is undefined it is allowed to the mysqlnd DEVELOPER to implement
+ any behaviour they like, including the one checked for in this test.
+ What the test does is cover an implementation detail of the mysqlnd library.
+ This implementation detail may, at any time, change without prior notice.
+ On the contrary, the mysqlnd way is a reasonable one and, maybe, one fine
+ day, after Klingons visited earh, becomes the official one. Meanwhile do
+ not rely on it.
+ */
+ if ($IS_MYSQLND && (7 !== ($tmp = mysqli_stmt_num_rows($stmt))))
+ printf("[54] Expecting int/7, got %s/%s\n", gettype($tmp), $tmp);
+
+ } else {
+ printf("[055] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ }
+
+ mysqli_stmt_close($stmt);
+
+ if (NULL !== ($tmp = mysqli_stmt_num_rows($stmt)))
+ printf("[056] Expecting NULL, got %s/%s\n");
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+run_tests.php don't fool me with your 'ungreedy' expression '.+?'!
+
+Warning: mysqli_stmt_num_rows(): Couldn't fetch mysqli_stmt in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_param_count.phpt b/ext/mysqli/tests/mysqli_stmt_param_count.phpt
new file mode 100644
index 0000000..3526956
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_param_count.phpt
@@ -0,0 +1,72 @@
+--TEST--
+mysqli_stmt_param_count()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_stmt_param_count()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_param_count($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (NULL !== ($tmp = mysqli_stmt_param_count($stmt)))
+ printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ function func_test_mysqli_stmt_param_count($stmt, $query, $expected, $offset) {
+
+ if (!mysqli_stmt_prepare($stmt, $query)) {
+ printf("[%03d] [%d] %s\n", $offset, mysqli_stmt_errno($stmt), mysqli_error($stmt));
+ return false;
+ }
+
+ if ($expected !== ($tmp = mysqli_stmt_param_count($stmt)))
+ printf("[%03d] Expecting %s/%d, got %s/%d\n", $offset + 3,
+ gettype($expected), $expected,
+ gettype($tmp), $tmp);
+ return true;
+ }
+
+ func_test_mysqli_stmt_param_count($stmt, "SELECT 1 AS a", 0, 10);
+ func_test_mysqli_stmt_param_count($stmt, "INSERT INTO test(id) VALUES (?)", 1, 20);
+ func_test_mysqli_stmt_param_count($stmt, "INSERT INTO test(id, label) VALUES (?, ?)", 2, 30);
+ func_test_mysqli_stmt_param_count($stmt, "INSERT INTO test(id, label) VALUES (?, '?')", 1, 40);
+
+ mysqli_stmt_close($stmt);
+
+ if (NULL !== ($tmp = mysqli_stmt_param_count($stmt)))
+ printf("[40] Expecting NULL, got %s/%s\n");
+
+ mysqli_close($link);
+
+ /* Check that the function alias exists. It's a deprecated function,
+ but we have not announce the removal so far, therefore we need to check for it */
+ if (!is_null($tmp = @mysqli_stmt_param_count()))
+ printf("[041] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Warning: mysqli_stmt_param_count(): invalid object or resource mysqli_stmt
+ in %s on line %d
+
+Warning: mysqli_stmt_param_count(): Couldn't fetch mysqli_stmt in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_prepare.phpt b/ext/mysqli/tests/mysqli_stmt_prepare.phpt
new file mode 100644
index 0000000..3eb576a
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_prepare.phpt
@@ -0,0 +1,56 @@
+--TEST--
+mysqli_stmt_prepare()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ // Note: No SQL tests here! We can expand one of the *fetch()
+ // tests to a generic SQL test, if we ever need that.
+ // We would duplicate the SQL test cases if we have it here and in one of the
+ // fetch tests, because the fetch tests would have to call prepare/execute etc.
+ // anyway.
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_stmt_prepare()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_prepare($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (NULL !== ($tmp = @mysqli_stmt_prepare($stmt)))
+ printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (false !== ($tmp = mysqli_stmt_prepare($stmt, '')))
+ printf("[005] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (true !== ($tmp = mysqli_stmt_prepare($stmt, 'SELECT id FROM test')))
+ printf("[006] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_stmt_close($stmt);
+
+ if (NULL !== ($tmp = mysqli_stmt_prepare($stmt, "SELECT id FROM test")))
+ printf("[007] Expecting NULL, got %s/%s\n");
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Warning: mysqli_stmt_prepare(): Couldn't fetch mysqli_stmt in %s on line %d
+done!
diff --git a/ext/mysqli/tests/mysqli_stmt_reset.phpt b/ext/mysqli/tests/mysqli_stmt_reset.phpt
new file mode 100644
index 0000000..d731da2
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_reset.phpt
@@ -0,0 +1,112 @@
+--TEST--
+mysqli_stmt_reset()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ // Note: No SQL tests here! We can expand one of the *fetch()
+ // tests to a generic SQL test, if we ever need that.
+ // We would duplicate the SQL test cases if we have it here and in one of the
+ // fetch tests, because the fetch tests would have to call prepare/execute etc.
+ // anyway.
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_stmt_reset()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_reset($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (NULL !== ($tmp = mysqli_stmt_reset($stmt)))
+ printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (true !== ($tmp = mysqli_stmt_prepare($stmt, 'SELECT id FROM test')))
+ printf("[005] Expecting boolean/true, got %s/%s, [%d] %s\n",
+ gettype($tmp), $tmp, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (true !== ($tmp = mysqli_stmt_reset($stmt)))
+ printf("[006] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (true !== ($tmp = mysqli_stmt_execute($stmt)))
+ printf("[007] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ $id = null;
+ if (!mysqli_stmt_bind_result($stmt, $id))
+ printf("[008] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_fetch($stmt))
+ printf("[009] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ var_dump($id);
+ mysqli_stmt_close($stmt);
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[010] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, "DROP TABLE IF EXISTS test"))
+ printf("[011] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, "CREATE TABLE test(id INT NOT NULL AUTO_INCREMENT, label BLOB, PRIMARY KEY(id))"))
+ printf("[012] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_stmt_prepare($stmt, "INSERT INTO test(label) VALUES (?)"))
+ printf("[013] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $label = null;
+ if (!mysqli_stmt_bind_param($stmt, "b", $label))
+ printf("[014] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $label = 'abc';
+ for ($i = 0; $i < 10; $i++) {
+ if (!mysqli_stmt_send_long_data($stmt, 0, $label))
+ printf("[015 - %d] [%d] %s\n", $i, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ }
+
+ if (!mysqli_stmt_reset($stmt))
+ printf("[016] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_execute($stmt))
+ printf("[017] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!$res = mysqli_query($link, "SELECT label FROM test"))
+ printf("[018] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$row = mysqli_fetch_assoc($res))
+ printf("[019] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ mysqli_free_result($res);
+
+ if ($row['label'] != '')
+ printf("[020] Expecting empty string, got string/%s\n", $row['label']);
+
+ mysqli_stmt_close($stmt);
+
+ if (NULL !== ($tmp = mysqli_stmt_reset($stmt)))
+ printf("[021] Expecting NULL, got %s/%s\n");
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Warning: mysqli_stmt_reset(): invalid object or resource mysqli_stmt
+ in %s on line %d
+int(1)
+
+Warning: mysqli_stmt_reset(): Couldn't fetch mysqli_stmt in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_result_metadata.phpt b/ext/mysqli/tests/mysqli_stmt_result_metadata.phpt
new file mode 100644
index 0000000..a38706f
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_result_metadata.phpt
@@ -0,0 +1,134 @@
+--TEST--
+mysqli_stmt_result_metadata()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_stmt_result_metadata()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_result_metadata($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (NULL !== ($tmp = mysqli_stmt_result_metadata($stmt)))
+ printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_prepare($stmt, "SELECT id, label FROM test"))
+ printf("[005] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!is_object(($res = mysqli_stmt_result_metadata($stmt))))
+ printf("[006] Expecting object, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (2 !== ($tmp = mysqli_num_fields($res)))
+ printf("[007] Expecting int/2, got %s/%s, [%d] %s\n",
+ gettype($tmp), $tmp, mysqli_errno($link), mysqli_error($link));
+
+ if (!is_object($field0_fetch = mysqli_fetch_field($res)))
+ printf("[008] Expecting object, got %s/%s, [%d] %s\n",
+ gettype($field0_fetch), $field0_fetch, mysqli_errno($link), mysqli_error($link));
+
+ if (!is_object($field0_direct = mysqli_fetch_field_direct($res, 0)))
+ printf("[009] Expecting object, got %s/%s, [%d] %s\n",
+ gettype($field0_direct), $field0_direct, mysqli_errno($link), mysqli_error($link));
+
+ if ($field0_fetch != $field0_direct) {
+ printf("[010] mysqli_fetch_field() differs from mysqli_fetch_field_direct()\n");
+ var_dump($field0_fetch);
+ var_dump($field0_direct);
+ }
+
+ var_dump($field0_fetch);
+
+ if (!is_array($tmp = mysqli_fetch_fields($res)))
+ printf("[011] Expecting array, got %s/%s, [%d] %s\n",
+ gettype($tmp), $tmp, mysqli_errno($link), mysqli_error($link));
+
+ if (empty($tmp[0]) || empty($tmp[1]) || $tmp[0] != $field0_direct) {
+ printf("[012] mysqli_fetch_fields() return value is suspicious\n");
+ var_dump($tmp);
+ }
+
+ if (!mysqli_field_seek($res, 1))
+ printf("[013] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!is_object($field1_direct = mysqli_fetch_field_direct($res, 1)))
+ printf("[014] Expecting object, got %s/%s, [%d] %s\n",
+ gettype($field1_direct), $field1_direct, mysqli_errno($link), mysqli_error($link));
+
+ if ($tmp[1] != $field1_direct) {
+ printf("[015] mysqli_fetch_field_direct() differs from mysqli_fetch_fields()\n");
+ var_dump($field1_direct);
+ var_dump($tmp);
+ }
+
+ if (1 !== ($tmp = mysqli_field_tell($res)))
+ printf("[016] Expecting int/1, got %s/%s, [%d] %s\n",
+ gettype($tmp), $tmp, mysqli_errno($link), mysqli_error($link));
+
+ mysqli_free_result($res);
+ mysqli_stmt_close($stmt);
+
+ if (NULL !== ($tmp = mysqli_stmt_result_metadata($stmt)))
+ printf("[017] Expecting NULL, got %s/%s\n");
+
+ /* Check that the function alias exists. It's a deprecated function,
+ but we have not announce the removal so far, therefore we need to check for it */
+ if (!is_null($tmp = @mysqli_stmt_result_metadata()))
+ printf("[018] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+
+Warning: mysqli_stmt_result_metadata(): invalid object or resource mysqli_stmt
+ in %s on line %d
+object(stdClass)#5 (13) {
+ [%u|b%"name"]=>
+ %unicode|string%(2) "id"
+ [%u|b%"orgname"]=>
+ %unicode|string%(2) "id"
+ [%u|b%"table"]=>
+ %unicode|string%(4) "test"
+ [%u|b%"orgtable"]=>
+ %unicode|string%(4) "test"
+ [%u|b%"def"]=>
+ %unicode|string%(0) ""
+ [%u|b%"db"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"catalog"]=>
+ %unicode|string%(%d) "%s"
+ [%u|b%"max_length"]=>
+ int(0)
+ [%u|b%"length"]=>
+ int(11)
+ [%u|b%"charsetnr"]=>
+ int(63)
+ [%u|b%"flags"]=>
+ int(49155)
+ [%u|b%"type"]=>
+ int(3)
+ [%u|b%"decimals"]=>
+ int(0)
+}
+
+Warning: mysqli_stmt_result_metadata(): Couldn't fetch mysqli_stmt in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_result_metadata_sqltests.phpt b/ext/mysqli/tests/mysqli_stmt_result_metadata_sqltests.phpt
new file mode 100644
index 0000000..a7dad1b
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_result_metadata_sqltests.phpt
@@ -0,0 +1,232 @@
+--TEST--
+mysqli_stmt_result_metadata() - non SELECT statements
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+die("skip Check again when the Klingons visit earth - http://bugs.mysql.com/bug.php?id=42490");
+?>
+--FILE--
+<?php
+ require('table.inc');
+
+ function testStatement($offset, $link, $sql, $expected_lib, $expected_mysqlnd, $check_mysqlnd, $compare) {
+
+ if (!$stmt = mysqli_stmt_init($link)) {
+ printf("[%04d - %s] [%d] %s\n",
+ $offset, $sql,
+ mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ if (!@mysqli_stmt_prepare($stmt, $sql)) {
+ /* Not all server versions will support all statements */
+ /* Failing to prepare is OK */
+ return true;
+ }
+
+ if (empty($expected_lib) && (false !== $res)) {
+ printf("[%04d - %s] No metadata expected\n",
+ $offset + 1, $sql);
+ return false;
+ } else if (!empty($expected_lib) && (false == $res)) {
+ printf("[%04d - %s] Metadata expected\n",
+ $offset + 2, $sql);
+ return false;
+ }
+ if (!empty($expected_lib)) {
+ if (!is_object($res)) {
+ printf("[%04d - %s] [%d] %s\n",
+ $offset + 3, $sql,
+ mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ return false;
+ }
+ if (get_class($res) != 'mysqli_result') {
+ printf("[%04d - %s] Expecting object/mysqli_result got object/%s\n",
+ $offset + 4, $sql, get_class($res));
+ return false;
+ }
+
+ $meta = array(
+ 'num_fields' => mysqli_num_fields($res),
+ 'fetch_field' => mysqli_fetch_field($res),
+ 'fetch_field_direct0' => mysqli_fetch_field_direct($res, 0),
+ 'fetch_field_direct1' => @mysqli_fetch_field_direct($res, 1),
+ 'fetch_fields' => count(mysqli_fetch_fields($res)),
+ 'field_count' => $res->field_count,
+ 'field_seek-1' => @mysqli_field_seek($res, -1),
+ 'field_seek0' => mysqli_field_seek($res, 0),
+ 'field_tell' => mysqli_field_tell($res),
+ );
+ if (is_object($meta['fetch_field'])) {
+ $meta['fetch_field']->charsetnr = 'ignore';
+ $meta['fetch_field']->flags = 'ignore';
+ }
+ if (is_object($meta['fetch_field_direct0'])) {
+ $meta['fetch_field_direct0']->charsetnr = 'ignore';
+ $meta['fetch_field_direct0']->flags = 'ignore';
+ }
+ if (is_object($meta['fetch_field_direct1'])) {
+ $meta['fetch_field_direct1']->charsetnr = 'ignore';
+ $meta['fetch_field_direct1']->flags = 'ignore';
+ }
+ mysqli_free_result($res);
+
+ if ($meta != $expected_lib) {
+ printf("[%04d - %s] Metadata differes from expected values\n",
+ $offset + 5, $sql);
+ var_dump($meta);
+ var_dump($expected_lib);
+ return false;
+ }
+ }
+
+ if (function_exists('mysqli_stmt_get_result')) {
+ /* mysqlnd only */
+ if (!mysqli_stmt_execute($stmt)) {
+ printf("[%04d - %s] [%d] %s\n",
+ $offset + 6, $sql,
+ mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ return false;
+ }
+
+ $res = mysqli_stmt_get_result($stmt);
+ if (false === $res && !empty($expected_mysqlnd)) {
+ printf("[%04d - %s] Expecting resultset [%d] %s\n",
+ $offset + 7, $sql,
+ mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ return false;
+ } else if (empty($expected_mysqlnd) && false !== $res) {
+ printf("[%04d - %s] Unexpected resultset [%d] %s\n",
+ $offset + 8, $sql,
+ mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ return false;
+ }
+
+ if (!is_object($res)) {
+ printf("[%04d - %s] [%d] %s\n",
+ $offset + 9, $sql,
+ mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ return false;
+ }
+ if ('mysqli_result' != get_class($res)) {
+ printf("[%04d - %s] Expecting object/mysqli_result got object/%s\n",
+ $offset + 10, $sql,
+ get_class($res));
+ return false;
+ }
+
+ $meta_res = array(
+ 'num_fields' => mysqli_num_fields($res),
+ 'fetch_field' => mysqli_fetch_field($res),
+ 'fetch_field_direct0' => mysqli_fetch_field_direct($res, 0),
+ 'fetch_field_direct1' => @mysqli_fetch_field_direct($res, 1),
+ 'fetch_fields' => count(mysqli_fetch_fields($res)),
+ 'field_count' => mysqli_field_count($link),
+ 'field_seek-1' => @mysqli_field_seek($res, -1),
+ 'field_seek0' => mysqli_field_seek($res, 0),
+ 'field_tell' => mysqli_field_tell($res),
+ );
+ if (is_object($meta_res['fetch_field'])) {
+ $meta_res['fetch_field']->charsetnr = 'ignore';
+ $meta_res['fetch_field']->flags = 'ignore';
+ }
+ if (is_object($meta_res['fetch_field_direct0'])) {
+ $meta_res['fetch_field_direct0']->charsetnr = 'ignore';
+ $meta_res['fetch_field_direct0']->flags = 'ignore';
+ }
+ if (is_object($meta_res['fetch_field_direct1'])) {
+ $meta_res['fetch_field_direct1']->charsetnr = 'ignore';
+ $meta_res['fetch_field_direct1']->flags = 'ignore';
+ }
+ mysqli_free_result($res);
+ if ($check_mysqlnd && $meta_res != $expected_mysqlnd) {
+ printf("[%04d - %s] Metadata differs from expected\n",
+ $offset + 11, $sql);
+ var_dump($meta_res);
+ var_dump($expected_mysqlnd);
+ } else {
+ if ($meta_res['field_count'] < 1) {
+ printf("[%04d - %s] Metadata seems wrong, no fields?\n",
+ $offset + 12, $sql);
+ var_dump($meta_res);
+ var_dump(mysqli_fetch_assoc($res));
+ }
+ }
+
+ if ($compare && $meta_res != $meta) {
+ printf("[%04d - %s] Metadata returned by mysqli_stmt_result_metadata() and mysqli_stmt_get_result() differ\n",
+ $offset + 13, $sql);
+ var_dump($meta_res);
+ var_dump($meta);
+ }
+
+ }
+
+ mysqli_stmt_close($stmt);
+ return true;
+ }
+
+ /* Note: very weak testing, we accept almost any result */
+
+ testStatement(100, $link, 'ANALYZE TABLE test', array(), array(1), false, false);
+ testStatement(120, $link, 'OPTIMIZE TABLE test', array(), array(1), false, false);
+ testStatement(140, $link, 'REPAIR TABLE test', array(), array(1), false, false);
+
+ testStatement(160, $link, 'SHOW AUTHORS', array(), array(1), false, false);
+ testStatement(180, $link, 'SHOW CHARACTER SET', array(), array(1), false, false);
+ testStatement(200, $link, 'SHOW COLLATION', array(), array(1), false, false);
+ testStatement(220, $link, 'SHOW CONTRIBUTORS', array(), array(1), false, false);
+ testStatement(240, $link, 'SHOW CREATE DATABASE ' . $db, array(), array(1), false, false);
+ testStatement(260, $link, 'SHOW DATABASES', array(), array(1), false, false);
+ testStatement(280, $link, 'SHOW ENGINE InnoDB STATUS', array(), array(1), false, false);
+ testStatement(300, $link, 'SHOW ENGINES', array(), array(1), false, false);
+ testStatement(320, $link, 'SHOW PLUGINS', array(), array(1), false, false);
+ testStatement(340, $link, 'SHOW PROCESSLIST', array(), array(1), false, false);
+ testStatement(360, $link, 'SHOW FULL PROCESSLIST', array(), array(1), false, false);
+ testStatement(380, $link, 'SHOW STATUS', array(), array(1), false, false);
+ testStatement(400, $link, 'SHOW TABLE STATUS', array(), array(1), false, false);
+ testStatement(420, $link, 'SHOW TABLE STATUS', array(), array(1), false, false);
+ testStatement(440, $link, 'SHOW TABLES', array(), array(1), false, false);
+ testStatement(460, $link, 'SHOW OPEN TABLES', array(), array(1), false, false);
+ testStatement(460, $link, 'SHOW VARIABLES', array(), array(1), false, false);
+
+ $field0 = new stdClass();
+ $field0->name = 'id';
+ $field0->orgname = 'id';
+ $field0->table = 'test';
+ $field0->orgtable = 'test';
+ $field0->def = '';
+ $field0->max_length = 0;
+ $field0->length = 11;
+ $field0->charsetnr = 'ignore';
+ $field0->flags = 'ignore';
+ $field0->type = MYSQLI_TYPE_LONG;
+ $field0->decimals = 0;
+ $meta_lib = array(
+ 'num_fields' => 1,
+ 'fetch_field' => $field0,
+ 'fetch_field_direct0' => $field0,
+ 'fetch_field_direct1' => false,
+ 'fetch_fields' => 1,
+ 'field_count' => 1,
+ 'field_seek-1' => false,
+ 'field_seek0' => true,
+ 'field_tell' => 0,
+ );
+ $meta_mysqlnd = $meta_lib;
+ testStatement(480, $link, 'SELECT id FROM test', $meta_lib, $meta_mysqlnd, true, true);
+
+ testStatement(500, $link, 'CHECKSUM TABLE test', array(), array(1), false, false);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_send_long_data.phpt b/ext/mysqli/tests/mysqli_stmt_send_long_data.phpt
new file mode 100644
index 0000000..7e2f860
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_send_long_data.phpt
@@ -0,0 +1,135 @@
+--TEST--
+mysqli_stmt_send_long_data()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_stmt_send_long_data()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_send_long_data($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (NULL !== ($tmp = @mysqli_stmt_send_long_data($stmt, '')))
+ printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_query($link, "DROP TABLE IF EXISTS test"))
+ printf("[005] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, sprintf("CREATE TABLE test(id INT NOT NULL AUTO_INCREMENT, label LONGBLOB, PRIMARY KEY(id)) ENGINE = %s", $engine)))
+ printf("[006] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_stmt_prepare($stmt, "INSERT INTO test(id, label) VALUES (?, ?)"))
+ printf("[007] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = null;
+ $label = null;
+ if (!mysqli_stmt_bind_param($stmt, "ib", $id, $label))
+ printf("[008] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!$res = mysqli_query($link, "SHOW VARIABLES LIKE 'max_allowed_packet'"))
+ printf("[009] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$row = mysqli_fetch_assoc($res))
+ printf("[010] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ mysqli_free_result($res);
+
+ if (isset($row['VARIABLE_VALUE']) && !isset($row['Value']))
+ // MySQL 6.0
+ $row['Value'] = $row['VARIABLE_VALUE'];
+
+ if (0 === ($max_allowed_packet = (int)$row['Value']))
+ printf("[011] Cannot determine max_allowed_packet size and/or bogus max_allowed_packet setting used.\n");
+
+ // let's ignore upper limits for LONGBLOB (2^32) ...
+ // maximum packet size up to which we test is 10M
+ $tmp = '';
+ $blob = '';
+ for ($i = 0; $i < 1024; $i++) {
+ $tmp .= 'a';
+ }
+
+ $limit = min(floor($max_allowed_packet / 1024 / 2), 10240);
+ for ($i = 0; $i < $limit; $i++)
+ $blob .= $tmp;
+ /*
+ if (floor($max_allowed_packet / 1024) <= 10240) {
+ $limit = strlen($blob) - $max_allowed_packet - 1;
+ for ($i = 0; $i < $limit; $i++)
+ $blob .= 'a';
+ }
+ */
+ assert(strlen($blob) <= $max_allowed_packet);
+
+ if (false !== ($tmp = mysqli_stmt_send_long_data($stmt, -1, $blob)))
+ printf("[012] Expecting boolean/false, got %s/%s. [%d] %s\n",
+ gettype($tmp), $tmp, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (false !== ($tmp = @mysqli_stmt_send_long_data($stmt, PHP_INT_MAX + 1, $blob)))
+ printf("[013] Expecting boolean/false, got %s/%s. [%d] %s\n",
+ gettype($tmp), $tmp, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (false !== ($tmp = mysqli_stmt_send_long_data($stmt, 999, $blob)))
+ printf("[014] Expecting boolean/false, got %s/%s. [%d] %s\n",
+ gettype($tmp), $tmp, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (true !== ($tmp = mysqli_stmt_send_long_data($stmt, 1, $blob)))
+ printf("[015] Expecting boolean/true, got %s/%s. [%d] %s\n",
+ gettype($tmp), $tmp, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = 1;
+ if (true !== mysqli_stmt_execute($stmt))
+ printf("[016] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ mysqli_stmt_close($stmt);
+
+ if (!$res = mysqli_query($link, "SELECT id, label FROM test ORDER BY id"))
+ printf("[017] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (1 != ($tmp = mysqli_num_rows($res)))
+ printf("[018] Expecting 1 rows, mysqli_num_rows() reports %d rows. [%d] %s\n",
+ $tmp, mysqli_errno($link), mysqli_error($link));
+
+ if (!$row = mysqli_fetch_assoc($res))
+ printf("[019] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ mysqli_free_result($res);
+
+ if (empty($row['id']) || empty($row['label']) || ($row['id'] != 1))
+ printf("[020] Record seems to be incomplete\n");
+
+ if ($blob != $row['label'])
+ printf("[021] Blob value has not been stored properly!\n");
+
+ if (NULL !== ($tmp = @mysqli_stmt_send_long_data($stmt, '')))
+ printf("[022] Expecting NULL, got %s/%s\n");
+
+ /* Check that the function alias exists. It's a deprecated function,
+ but we have not announce the removal so far, therefore we need to check for it */
+ if (!is_null($tmp = @mysqli_stmt_send_long_data()))
+ printf("[023] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Warning: mysqli_stmt_send_long_data(): Invalid parameter number in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_send_long_data_packet_size_libmysql.phpt b/ext/mysqli/tests/mysqli_stmt_send_long_data_packet_size_libmysql.phpt
new file mode 100644
index 0000000..a1fc200
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_send_long_data_packet_size_libmysql.phpt
@@ -0,0 +1,98 @@
+--TEST--
+mysqli_stmt_send_long_data() - exceed packet size, libmysql - bug #26824
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+if (stristr(mysqli_get_client_info(), 'mysqlnd'))
+ die("skip: test for libmysql");
+?>
+--FILE--
+<?php
+ require('table.inc');
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[001] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, "DROP TABLE IF EXISTS test"))
+ printf("[002] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, sprintf("CREATE TABLE test(id INT NOT NULL AUTO_INCREMENT, label LONGBLOB, PRIMARY KEY(id)) ENGINE = %s", $engine)))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_stmt_prepare($stmt, "INSERT INTO test(id, label) VALUES (?, ?)"))
+ printf("[004] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = null;
+ $label = null;
+ if (!mysqli_stmt_bind_param($stmt, "ib", $id, $label))
+ printf("[005] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!$res = mysqli_query($link, "SHOW VARIABLES LIKE 'max_allowed_packet'"))
+ printf("[006] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$row = mysqli_fetch_assoc($res))
+ printf("[007] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ mysqli_free_result($res);
+
+ if (0 === ($max_allowed_packet = (int)$row['Value']))
+ printf("[008] Cannot determine max_allowed_packet size and/or bogus max_allowed_packet setting used.\n");
+
+ // let's ignore upper limits for LONGBLOB (2^32) ...
+ // maximum packet size up to which we test is 10M
+ $tmp = '';
+ $blob = '';
+ for ($i = 0; $i < 1024; $i++) {
+ $tmp .= 'a';
+ }
+
+ $limit = min(floor($max_allowed_packet / 1024 / 2), 10240);
+ for ($i = 0; $i < $limit; $i++)
+ $blob .= $tmp;
+
+ assert(strlen($blob) <= $max_allowed_packet);
+
+ if (true != ($tmp = mysqli_stmt_send_long_data($stmt, 1, $blob)))
+ printf("[009] Expecting boolean/true, got %s/%s. [%d] %s\n",
+ gettype($tmp), $tmp, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = 1;
+ if (true !== mysqli_stmt_execute($stmt))
+ printf("[010] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ /*
+ TODO - we skip this part of the test for now, because of bugs.mysql.com/26824
+ if (floor($max_allowed_packet / 1024 / 2) <= 10240) {
+ // test with a blob smaller than 10M allows us to test
+ // for too long packages without wasting too much memory
+ $limit = $max_allowed_packet - strlen($blob) + 1;
+ $blob2 = $blob;
+ for ($i = 0; $i < $limit; $i++)
+ $blob2 .= 'b';
+
+ assert(strlen($blob2) > $max_allowed_packet);
+
+ if (true != ($tmp = mysqli_stmt_send_long_data($stmt, 1, $blob2)))
+ printf("[011] Expecting boolean/false, got %s/%s. [%d] %s\n",
+ gettype($tmp), $tmp, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = 2;
+ if (false !== ($tmp = mysqli_stmt_execute($stmt)))
+ printf("[012] Expecting boolean/false, got %s/%s, [%d] %s\n",
+ gettype($tmp), $tmp, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ }
+ */
+ mysqli_stmt_close($stmt);
+ mysqli_close($link);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_send_long_data_packet_size_mysqlnd.phpt b/ext/mysqli/tests/mysqli_stmt_send_long_data_packet_size_mysqlnd.phpt
new file mode 100644
index 0000000..95d2302
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_send_long_data_packet_size_mysqlnd.phpt
@@ -0,0 +1,103 @@
+--TEST--
+mysqli_stmt_send_long_data() - exceed packet size, mysqlnd
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+if (!stristr(mysqli_get_client_info(), 'mysqlnd'))
+ die("skip: warnings only available in mysqlnd");
+?>
+--FILE--
+<?php
+ require('table.inc');
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[001] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, "DROP TABLE IF EXISTS test"))
+ printf("[002] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, sprintf("CREATE TABLE test(id INT NOT NULL AUTO_INCREMENT, label LONGBLOB, PRIMARY KEY(id)) ENGINE = %s", $engine)))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_stmt_prepare($stmt, "INSERT INTO test(id, label) VALUES (?, ?)"))
+ printf("[004] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = null;
+ $label = null;
+ if (!mysqli_stmt_bind_param($stmt, "ib", $id, $label))
+ printf("[005] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!$res = mysqli_query($link, "SHOW VARIABLES LIKE 'max_allowed_packet'"))
+ printf("[006] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$row = mysqli_fetch_assoc($res))
+ printf("[007] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ mysqli_free_result($res);
+
+ if (0 === ($max_allowed_packet = (int)$row['Value']))
+ printf("[008] Cannot determine max_allowed_packet size and/or bogus max_allowed_packet setting used.\n");
+
+ // let's ignore upper limits for LONGBLOB (2^32) ...
+ // maximum packet size up to which we test is 10M
+ $tmp = '';
+ $blob = '';
+ $tmp = str_repeat('a', 1024);
+
+ $limit = min(floor($max_allowed_packet / 1024 / 2), 10240);
+ $blob = str_repeat($tmp, $limit);
+
+ assert(strlen($blob) <= $max_allowed_packet);
+
+ if (true !== ($tmp = mysqli_stmt_send_long_data($stmt, 1, $blob)))
+ printf("[009] Expecting boolean/true, got %s/%s. [%d] %s\n",
+ gettype($tmp), $tmp, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = 1;
+ if (true !== mysqli_stmt_execute($stmt))
+ printf("[010] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ /*
+ TODO - we skip this because of the open bug http://bugs.mysql.com/bug.php?id=26824
+ It would always fail.
+
+ This should be added to the EXPECTF, if you reactivate the test
+Warning: mysqli_stmt_send_long_data(): Skipped %d bytes. Last command STMT_SEND_LONG_DATA hasn't consumed all the output from the server in %s on line %d
+
+Warning: mysqli_stmt_send_long_data(): There was an error while sending long data. Probably max_allowed_packet_size is smaller than the data. You have to increase it or send smaller chunks of data. Answer was %d bytes long. in %s on line %d
+
+
+
+ if (floor($max_allowed_packet / 1024 / 2) <= 10240) {
+ // test with a blob smaller than 10M allows us to test
+ // for too long packages without wasting too much memory
+ $limit = $max_allowed_packet - strlen($blob) + 1;
+ $blob2 = $blob;
+ $blob2 .= str_repeat('b', $limit);
+
+ assert(strlen($blob2) > $max_allowed_packet);
+
+ if (false !== ($tmp = mysqli_stmt_send_long_data($stmt, 1, $blob2)))
+ printf("[011] Expecting boolean/false, got %s/%s. [%d] %s\n",
+ gettype($tmp), $tmp, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = 2;
+ if (false !== ($tmp = mysqli_stmt_execute($stmt)))
+ printf("[012] Expecting boolean/false, got %s/%s, [%d] %s\n",
+ gettype($tmp), $tmp, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ }
+ */
+ mysqli_stmt_close($stmt);
+ mysqli_close($link);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_sqlstate.phpt b/ext/mysqli/tests/mysqli_stmt_sqlstate.phpt
new file mode 100644
index 0000000..5ea35df
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_sqlstate.phpt
@@ -0,0 +1,63 @@
+--TEST--
+mysqli_stmt_sqlstate()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_stmt_sqlstate()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_sqlstate($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (!is_null($tmp = @mysqli_stmt_sqlstate($link, '')))
+ printf("[003] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[004] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (NULL !== ($tmp = mysqli_stmt_sqlstate($stmt)))
+ printf("[005] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_prepare($stmt, "SELECT id FROM test"))
+ printf("[006] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if ('00000' !== ($tmp = mysqli_stmt_sqlstate($stmt)))
+ printf("[007] Expecting string/00000, got %s/%s. [%d] %s\n",
+ gettype($tmp), $tmp, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (mysqli_stmt_prepare($stmt, "SELECT believe_me FROM i_dont_belive_that_this_table_exists"))
+ printf("[008] Should fail! [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if ('' === ($tmp = mysqli_stmt_sqlstate($stmt)))
+ printf("[009] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ mysqli_stmt_close($stmt);
+
+ if (NULL !== ($tmp = mysqli_stmt_sqlstate($stmt)))
+ printf("[010] Expecting NULL, got %s/%s\n");
+
+ mysqli_close($link);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Warning: mysqli_stmt_sqlstate(): invalid object or resource mysqli_stmt
+ in %s on line %d
+
+Warning: mysqli_stmt_sqlstate(): Couldn't fetch mysqli_stmt in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_store_result.phpt b/ext/mysqli/tests/mysqli_stmt_store_result.phpt
new file mode 100644
index 0000000..a6411ca
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_store_result.phpt
@@ -0,0 +1,90 @@
+--TEST--
+mysqli_stmt_store_result()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_stmt_store_result()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_store_result($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (!is_null($tmp = @mysqli_stmt_store_result(new mysqli_stmt())))
+ printf("[003] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[004] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ // stmt object status test
+ if (NULL !== ($tmp = @mysqli_stmt_store_result($stmt)))
+ printf("[005] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_prepare($stmt, "INSERT INTO test(id, label) VALUES (100, 'z')") ||
+ !mysqli_stmt_execute($stmt))
+ printf("[006] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (true !== ($tmp = @mysqli_stmt_store_result($stmt)))
+ printf("[007] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_prepare($stmt, 'SELECT id, label FROM test ORDER BY id') ||
+ !mysqli_stmt_execute($stmt))
+ printf("[008] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!$link_buf = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[009] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+ if (!$stmt_buf = mysqli_stmt_init($link_buf))
+ printf("[010] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_stmt_prepare($stmt_buf, "SELECT id, label FROM test ORDER BY id") ||
+ !mysqli_stmt_execute($stmt_buf))
+ printf("[011] [%d] %s\n", mysqli_stmt_errno($stmt_buf), mysqli_stmt_error($stmt_buf));
+
+ $id = $label = $id_buf = $label_buf = null;
+ if (!mysqli_stmt_bind_result($stmt, $id, $label))
+ printf("[012] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_bind_result($stmt_buf, $id_buf, $label_buf))
+ printf("[013] [%d] %s\n", mysqli_stmt_errno($stmt_buf), mysqli_stmt_error($stmt_buf));
+
+ while (mysqli_stmt_fetch($stmt)) {
+ if (!mysqli_stmt_fetch($stmt_buf)) {
+ printf("[014] Unbuffered statement indicates more rows than buffered, [%d] %s\n",
+ mysqli_stmt_errno($stmt_buf), mysqli_stmt_error($stmt_buf));
+ }
+ if ($id !== $id_buf)
+ printf("[015] unbuffered '%s'/%s, buffered '%s'/%s\n",
+ $id, gettype($id), $id_buf, gettype($id_buf));
+ if ($label !== $label_buf)
+ printf("[016] unbuffered '%s'/%s, buffered '%s'/%s\n",
+ $label, gettype($label), $label_buf, gettype($label_buf));
+ }
+
+ mysqli_stmt_close($stmt);
+ mysqli_stmt_close($stmt_buf);
+
+ if (NULL !== ($tmp = @mysqli_stmt_store_result($stmt)))
+ printf("[017] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_close($link);
+ mysqli_close($link_buf);
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_unclonable.phpt b/ext/mysqli/tests/mysqli_stmt_unclonable.phpt
new file mode 100644
index 0000000..57d8d6d
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_unclonable.phpt
@@ -0,0 +1,25 @@
+--TEST--
+Trying to clone mysqli_stmt object
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[001] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[002] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ /* no, still bails out */
+ $stmt_clone = clone $stmt;
+ print "done!";
+?>
+--EXPECTF--
+Fatal error: Trying to clone an uncloneable object of class mysqli_stmt in %s on line %d \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_store_result.phpt b/ext/mysqli/tests/mysqli_store_result.phpt
new file mode 100644
index 0000000..c61c124
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_store_result.phpt
@@ -0,0 +1,64 @@
+--TEST--
+mysqli_store_result()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_store_result()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_store_result($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (!$res = mysqli_real_query($link, "SELECT id, label FROM test ORDER BY id"))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!is_object($res = mysqli_store_result($link)))
+ printf("[004] Expecting object, got %s/%s. [%d] %s\n",
+ gettype($res), $res, mysqli_errno($link), mysqli_error($link));
+
+ if (true !== ($tmp = mysqli_data_seek($res, 2)))
+ printf("[005] Expecting boolean/true, got %s/%s. [%d] %s\n",
+ gettype($tmp), $tmp, mysqli_errno($link), mysqli_error($link));
+
+ mysqli_free_result($res);
+
+ if (!mysqli_query($link, "DELETE FROM test"))
+ printf("[006] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (false !== ($res = mysqli_store_result($link)))
+ printf("[007] Expecting boolean/false, got %s/%s. [%d] %s\n",
+ gettype($res), $res, mysqli_errno($link), mysqli_error($link));
+
+ if (!$res = mysqli_query($link, "SELECT id, label FROM test ORDER BY id"))
+ printf("[008] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (false !== ($tmp = mysqli_data_seek($res, 1)))
+ printf("[009] Expecting boolean/false, got %s/%s\n",
+ gettype($tmp), $tmp);
+
+ mysqli_close($link);
+
+ if (NULL !== ($tmp = mysqli_store_result($link)))
+ printf("[010] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Warning: mysqli_store_result(): Couldn't fetch mysqli in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_thread_id.phpt b/ext/mysqli/tests/mysqli_thread_id.phpt
new file mode 100644
index 0000000..3a7e1ae
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_thread_id.phpt
@@ -0,0 +1,44 @@
+--TEST--
+mysqli_thread_id()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_thread_id()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_thread_id($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (!is_int($tmp = mysqli_thread_id($link)) || (0 === $tmp))
+ printf("[003] Expecting int/any but zero, got %s/%s. [%d] %s\n",
+ gettype($tmp), $tmp, mysqli_errno($link), mysqli_error($link));
+
+ // should work if the thread id is correct
+ mysqli_kill($link, mysqli_thread_id($link));
+
+ mysqli_close($link);
+
+ if (NULL !== ($tmp = mysqli_thread_id($link)))
+ printf("[005] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Warning: mysqli_thread_id(): Couldn't fetch mysqli in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_thread_safe.phpt b/ext/mysqli/tests/mysqli_thread_safe.phpt
new file mode 100644
index 0000000..0777c2a
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_thread_safe.phpt
@@ -0,0 +1,16 @@
+--TEST--
+mysqli_thread_safe()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+?>
+--FILE--
+<?php
+ if (!is_bool($tmp = mysqli_thread_safe()))
+ printf("[001] Expecting boolean/any, got %s/%s.\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_unclonable.phpt b/ext/mysqli/tests/mysqli_unclonable.phpt
new file mode 100644
index 0000000..e332b9f
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_unclonable.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Trying to clone mysqli object
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[001] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ $link_clone = clone $link;
+ mysqli_close($link);
+
+ print "done!";
+?>
+--EXPECTF--
+Fatal error: Trying to clone an uncloneable object of class mysqli in %s on line %d \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_use_result.phpt b/ext/mysqli/tests/mysqli_use_result.phpt
new file mode 100644
index 0000000..25d1692
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_use_result.phpt
@@ -0,0 +1,66 @@
+--TEST--
+mysqli_use_result()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_use_result()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_use_result($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (!$res = mysqli_real_query($link, "SELECT id, label FROM test ORDER BY id"))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!is_object($res = mysqli_use_result($link)))
+ printf("[004] Expecting object, got %s/%s. [%d] %s\n",
+ gettype($res), $res, mysqli_errno($link), mysqli_error($link));
+
+ if (false !== ($tmp = mysqli_data_seek($res, 2)))
+ printf("[005] Expecting boolean/true, got %s/%s. [%d] %s\n",
+ gettype($tmp), $tmp, mysqli_errno($link), mysqli_error($link));
+
+ mysqli_free_result($res);
+
+ if (!mysqli_query($link, "DELETE FROM test"))
+ printf("[006] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (false !== ($res = mysqli_use_result($link)))
+ printf("[007] Expecting boolean/false, got %s/%s. [%d] %s\n",
+ gettype($res), $res, mysqli_errno($link), mysqli_error($link));
+
+ if (!$res = mysqli_query($link, "SELECT id, label FROM test ORDER BY id"))
+ printf("[008] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (false !== ($tmp = mysqli_data_seek($res, 1)))
+ printf("[009] Expecting boolean/false, got %s/%s\n",
+ gettype($tmp), $tmp);
+
+ mysqli_close($link);
+
+ if (NULL !== ($tmp = mysqli_use_result($link)))
+ printf("[010] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Warning: mysqli_data_seek(): Function cannot be used with MYSQL_USE_RESULT in %s on line %d
+
+Warning: mysqli_use_result(): Couldn't fetch mysqli in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_warning_count.phpt b/ext/mysqli/tests/mysqli_warning_count.phpt
new file mode 100644
index 0000000..cff9c02
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_warning_count.phpt
@@ -0,0 +1,52 @@
+--TEST--
+mysqli_warning_count()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_warning_count()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_warning_count($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (NULL !== ($tmp = @mysqli_warning_count($link, "too_many")))
+ printf("[003] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$res = mysqli_query($link, "SELECT id, label FROM test"))
+ printf("[004] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (0 !== ($tmp = mysqli_warning_count($link)))
+ printf("[005] Expecting int/0, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_query($link, "DROP TABLE IF EXISTS this_table_does_not_exist"))
+ printf("[006] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (1 !== ($tmp = mysqli_warning_count($link)))
+ printf("[007] Expecting int/1, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_close($link);
+
+ if (NULL !== ($tmp = mysqli_warning_count($link)))
+ printf("[010] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Warning: mysqli_warning_count(): Couldn't fetch mysqli in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_warning_unclonable.phpt b/ext/mysqli/tests/mysqli_warning_unclonable.phpt
new file mode 100644
index 0000000..d3ae47d
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_warning_unclonable.phpt
@@ -0,0 +1,41 @@
+--TEST--
+Trying to clone mysqli_warning object
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+require_once('connect.inc');
+if (!$TEST_EXPERIMENTAL)
+ die("skip - experimental (= unsupported) feature");
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[001] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ if (!mysqli_query($link, "DROP TABLE IF EXISTS test"))
+ printf("[002] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, "CREATE TABLE test (id SMALLINT)"))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, "INSERT INTO test (id) VALUES (1000000)"))
+ printf("[004] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!is_object($warning = mysqli_get_warnings($link)) || 'mysqli_warning' != get_class($warning)) {
+ printf("[005] Expecting object/mysqli_warning, got %s/%s\n", gettype($tmp), (is_object($tmp) ? var_dump($tmp, true) : $tmp));
+ }
+
+ $warning_clone = clone $warning;
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Fatal error: Trying to clone an uncloneable object of class mysqli_warning in %s on line %d \ No newline at end of file
diff --git a/ext/mysqli/tests/reflection_tools.inc b/ext/mysqli/tests/reflection_tools.inc
new file mode 100644
index 0000000..c8338bf
--- /dev/null
+++ b/ext/mysqli/tests/reflection_tools.inc
@@ -0,0 +1,121 @@
+<?php
+ function inspectClass($class) {
+
+ /* not used: public ReflectionClass[] getInterfaces() */
+
+ printf("\nInspecting class '%s'\n", $class->getName());
+ printf("isInternal: %s\n", ($class->isInternal()) ? 'yes' : 'no');
+ printf("isUserDefined: %s\n", ($class->isUserDefined()) ? 'yes' : 'no');
+ printf("isInstantiable: %s\n", ($class->isInstantiable()) ? 'yes' : 'no');
+ printf("isInterface: %s\n", ($class->isInterface()) ? 'yes' : 'no');
+ printf("isAbstract: %s\n", ($class->isAbstract()) ? 'yes' : 'no');
+ printf("isFinal: %s\n", ($class->isFinal()) ? 'yes' : 'no');
+ printf("isIteratable: %s\n", ($class->isIterateable()) ? 'yes' : 'no');
+ printf("Modifiers: '%d'\n", $class->getModifiers());
+ printf("Parent Class: '%s'\n", $class->getParentClass());
+ printf("Extension: '%s'\n", $class->getExtensionName());
+
+ if ($method = $class->getConstructor())
+ inspectMethod($method);
+
+ if ($methods = $class->getMethods()) {
+ $tmp = array();
+ foreach ($methods as $method)
+ $tmp[$method->getName()] = $method;
+
+ ksort($tmp, SORT_STRING);
+ foreach ($tmp as $method)
+ inspectMethod($method);
+ }
+
+ if ($properties = $class->getProperties()) {
+ $tmp = array();
+ foreach ($properties as $prop)
+ $tmp[$prop->getName()] = $prop;
+ ksort($tmp, SORT_STRING);
+ foreach ($tmp as $prop)
+ inspectProperty($prop);
+ }
+
+
+ if ($properties = $class->getDefaultProperties()) {
+ ksort($properties, SORT_STRING);
+ foreach ($properties as $name => $v)
+ printf("Default property '%s'\n", $name);
+ }
+
+ if ($properties = $class->getStaticProperties()) {
+ ksort($properties, SORT_STRING);
+ foreach ($properties as $name => $v)
+ printf("Static property '%s'\n", $name);
+ }
+
+ if ($constants = $class->getConstants()) {
+ ksort($constants, SORT_STRING);
+ foreach ($constant as $name => $value)
+ printf("Constant '%s' = '%s'\n", $name, $value);
+ }
+
+ }
+
+ function inspectProperty(&$prop) {
+
+ printf("\nInspecting property '%s'\n", $prop->getName());
+ printf("isPublic: %s\n", ($prop->isPublic()) ? 'yes' : 'no');
+ printf("isPrivate: %s\n", ($prop->isPrivate()) ? 'yes' : 'no');
+ printf("isProtected: %s\n", ($prop->isProtected()) ? 'yes' : 'no');
+ printf("isStatic: %s\n", ($prop->isStatic()) ? 'yes' : 'no');
+ printf("isDefault: %s\n", ($prop->isDefault()) ? 'yes' : 'no');
+ printf("Modifiers: %d\n", $prop->getModifiers());
+ // printf("Value\n"); var_export($prop->getValue());
+
+ }
+
+ function inspectMethod(&$method) {
+
+ printf("\nInspecting method '%s'\n", $method->getName());
+ printf("isFinal: %s\n", ($method->isFinal()) ? 'yes' : 'no');
+ printf("isAbstract: %s\n", ($method->isAbstract()) ? 'yes' : 'no');
+ printf("isPublic: %s\n", ($method->isPublic()) ? 'yes' : 'no');
+ printf("isPrivate: %s\n", ($method->isPrivate()) ? 'yes' : 'no');
+ printf("isProtected: %s\n", ($method->isProtected()) ? 'yes' : 'no');
+ printf("isStatic: %s\n", ($method->isStatic()) ? 'yes' : 'no');
+ printf("isConstructor: %s\n", ($method->isConstructor()) ? 'yes' : 'no');
+ printf("isDestructor: %s\n", ($method->isDestructor()) ? 'yes' : 'no');
+ printf("isInternal: %s\n", ($method->isInternal()) ? 'yes' : 'no');
+ printf("isUserDefined: %s\n", ($method->isUserDefined()) ? 'yes' : 'no');
+ printf("returnsReference: %s\n", ($method->returnsReference()) ? 'yes' : 'no');
+ printf("Modifiers: %d\n", $method->getModifiers());
+ printf("Number of Parameters: %d\n", $method->getNumberOfParameters());
+ printf("Number of Required Parameters: %d\n", $method->getNumberOfRequiredParameters());
+
+ if ($params = $method->getParameters()) {
+ $tmp = array();
+ foreach ($params as $k => $param)
+ $tmp[$param->getName()] = $param;
+
+// ksort($tmp, SORT_STRING);
+ foreach ($tmp as $param)
+ inspectParameter($method, $param);
+ }
+
+ if ($static = $method->getStaticVariables()) {
+ sort($static, SORT_STRING);
+ printf("Static variables: %s\n", implode('/', $static));
+ }
+
+ }
+
+ function inspectParameter(&$method, &$param) {
+
+ printf("\nInspecting parameter '%s' of method '%s'\n",
+ $param->getName(), $method->getName());
+ printf("isArray: %s\n", ($param->isArray()) ? 'yes': 'no');
+ printf("allowsNull: %s\n", ($param->allowsNull()) ? 'yes' : 'no');
+ printf("isPassedByReference: %s\n", ($param->isPassedByReference()) ? 'yes' : 'no');
+ printf("isOptional: %s\n", ($param->isOptional()) ? 'yes' : 'no');
+ printf("isDefaultValueAvailable: %s\n", ($param->isDefaultValueAvailable()) ? 'yes' : 'no');
+ // printf("getDefaultValue: %s\n", ($param->getDefaultValue()) ? 'yes' : 'no');
+
+ }
+?> \ No newline at end of file
diff --git a/ext/mysqli/tests/skipif.inc b/ext/mysqli/tests/skipif.inc
new file mode 100644
index 0000000..a7581fb
--- /dev/null
+++ b/ext/mysqli/tests/skipif.inc
@@ -0,0 +1,5 @@
+<?php
+if (!extension_loaded('mysqli')){
+ die('skip mysqli extension not available');
+}
+?> \ No newline at end of file
diff --git a/ext/mysqli/tests/skipifconnectfailure.inc b/ext/mysqli/tests/skipifconnectfailure.inc
new file mode 100644
index 0000000..32a9763
--- /dev/null
+++ b/ext/mysqli/tests/skipifconnectfailure.inc
@@ -0,0 +1,10 @@
+<?php
+require_once('connect.inc');
+if ($skip_on_connect_failure) {
+ include_once('connect.inc');
+ $link = @my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+ if (!is_object($link))
+ die(sprintf("skip Can't connect to MySQL Server - [%d] %s", mysqli_connect_errno(), mysqli_connect_error()));
+ mysqli_close($link);
+}
+?>
diff --git a/ext/mysqli/tests/skipifemb.inc b/ext/mysqli/tests/skipifemb.inc
new file mode 100644
index 0000000..254a4cc
--- /dev/null
+++ b/ext/mysqli/tests/skipifemb.inc
@@ -0,0 +1,5 @@
+<?php
+ $driver = new mysqli_driver();
+ if ($driver->embedded)
+ die("skip test doesn't run with embedded server");
+?> \ No newline at end of file
diff --git a/ext/mysqli/tests/skipifnotemb.inc b/ext/mysqli/tests/skipifnotemb.inc
new file mode 100644
index 0000000..d73d185
--- /dev/null
+++ b/ext/mysqli/tests/skipifnotemb.inc
@@ -0,0 +1,5 @@
+<?php
+ $driver = new mysqli_driver();
+ if (!$driver->embedded)
+ die("skip test for with embedded server only");
+?> \ No newline at end of file
diff --git a/ext/mysqli/tests/skipifunicode.inc b/ext/mysqli/tests/skipifunicode.inc
new file mode 100644
index 0000000..da4dd8e
--- /dev/null
+++ b/ext/mysqli/tests/skipifunicode.inc
@@ -0,0 +1,5 @@
+<?php
+if (version_compare(PHP_VERSION, '5.9.9', '>') == 1) {
+ die('skip Not functional with PHP 6 (fomerly PHP 6 && unicode.semantics=On)');
+}
+?>
diff --git a/ext/mysqli/tests/table.inc b/ext/mysqli/tests/table.inc
new file mode 100644
index 0000000..aa1207a
--- /dev/null
+++ b/ext/mysqli/tests/table.inc
@@ -0,0 +1,23 @@
+<?PHP
+require_once('connect.inc');
+
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ printf("Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+ exit(1);
+}
+
+if (!mysqli_query($link, 'DROP TABLE IF EXISTS test')) {
+ printf("Failed to drop old test table: [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ exit(1);
+}
+
+if (!mysqli_query($link, 'CREATE TABLE test(id INT, label CHAR(1), PRIMARY KEY(id)) ENGINE=' . $engine)) {
+ printf("Failed to create test table: [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ exit(1);
+}
+
+if (!mysqli_query($link, "INSERT INTO test(id, label) VALUES (1, 'a'), (2, 'b'), (3, 'c'), (4, 'd'), (5, 'e'), (6, 'f')")) {
+ printf("[%d] %s\n", mysqli_errno($link), mysqli_error($link));
+}
+?> \ No newline at end of file