From ce8bf087b0abe3a1cae976a26cac5368a93ba1a7 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 17 Oct 2007 20:08:58 +0400 Subject: Fix for bug #31207: Test "join_nested" shows different strategy on IA64 CPUs / Intel's ICC compile The bug is a combination of two problems: 1. IA64/ICC MySQL binaries use glibc's qsort(), not the one in mysys. 2. The order relation implemented by join_tab_cmp() is not transitive, i.e. it is possible to choose such a, b and c that (a < b) && (b < c) but (c < a). This implies that result of a sort using the relation implemented by join_tab_cmp() depends on the order in which elements are compared, i.e. the result is implementation-specific. Since choose_plan() uses qsort() to pre-sort the join tables using join_tab_cmp() as a compare function, the results of the sorting may vary depending on qsort() implementation. It is neither possible nor important to implement a better ordering algorithm in join_tab_cmp(). Therefore the only way to fix it is to force our own qsort() to be used by renaming it to my_qsort(), so we don't depend on linker to decide that. This patch also "fixes" bug #20530: qsort redefinition violates the standard. include/my_sys.h: Renamed qsort() and qsort2() to my_qsort() and my_qsort2(). Since previously we relied on stdlib.h to provide a declaration for qsort(), a separate declaration for my_qsort() is now required. libmysql/Makefile.shared: Added mf_qsort.c to libmysql, since my_lib.c now uses my_qsort() instead of qsort(). myisam/ft_boolean_search.c: Replaced qsort2() with my_qsort2(). myisam/ft_nlq_search.c: Replaced qsort2() with my_qsort2(). myisam/myisampack.c: Replaced qsort() with my_qsort(). myisam/sort.c: Replaced qsort2() with my_qsort2(). mysys/mf_keycache.c: Replaced qsort() with my_qsort(). mysys/mf_qsort.c: Renamed qsort() to my_qsort() and qsort2() to my_qsort2(). mysys/mf_sort.c: Replaced qsort2() with my_qsort2(). mysys/my_lib.c: Replaced qsort() with my_qsort(). mysys/queues.c: Replaced qsort2() with my_qsort2(). sql/item_cmpfunc.cc: Replaced qsort2() with my_qsort2(). sql/item_cmpfunc.h: Replaced qsort2() with my_qsort2(). sql/opt_range.cc: Replaced qsort() with my_qsort(). sql/records.cc: Replaced qsort() with my_qsort(). sql/sql_acl.cc: Replaced qsort() with my_qsort(). sql/sql_array.h: Replaced qsort() with my_qsort(). sql/sql_help.cc: Replaced qsort() with my_qsort(). sql/sql_select.cc: Replaced qsort() with my_qsort(). sql/examples/ha_tina.cc: Replaced qsort() with my_qsort(). sql/sql_table.cc: Replaced qsort() with my_qsort(). --- sql/sql_select.cc | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'sql/sql_select.cc') diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 1d11f23d854..b519c06420f 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -3658,7 +3658,7 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab, { KEYUSE key_end,*prev,*save_pos,*use; - qsort(keyuse->buffer,keyuse->elements,sizeof(KEYUSE), + my_qsort(keyuse->buffer,keyuse->elements,sizeof(KEYUSE), (qsort_cmp) sort_keyuse); bzero((char*) &key_end,sizeof(key_end)); /* Add for easy testing */ @@ -4371,8 +4371,9 @@ choose_plan(JOIN *join, table_map join_tables) Apply heuristic: pre-sort all access plans with respect to the number of records accessed. */ - qsort(join->best_ref + join->const_tables, join->tables - join->const_tables, - sizeof(JOIN_TAB*), straight_join?join_tab_cmp_straight:join_tab_cmp); + my_qsort(join->best_ref + join->const_tables, + join->tables - join->const_tables, sizeof(JOIN_TAB*), + straight_join ? join_tab_cmp_straight : join_tab_cmp); if (straight_join) { @@ -4421,6 +4422,17 @@ choose_plan(JOIN *join, table_map join_tables) ptr1 pointer to first JOIN_TAB object ptr2 pointer to second JOIN_TAB object + NOTES + The order relation implemented by join_tab_cmp() is not transitive, + i.e. it is possible to choose such a, b and c that (a < b) && (b < c) + but (c < a). This implies that result of a sort using the relation + implemented by join_tab_cmp() depends on the order in which + elements are compared, i.e. the result is implementation-specific. + Example: + a: dependent = 0x0 table->map = 0x1 found_records = 3 ptr = 0x907e6b0 + b: dependent = 0x0 table->map = 0x2 found_records = 3 ptr = 0x907e838 + c: dependent = 0x6 table->map = 0x10 found_records = 2 ptr = 0x907ecd0 + RETURN 1 if first is bigger -1 if second is bigger -- cgit v1.2.1