Merge lp:~paul-mccullagh/maria/maria-pbxt-1009g into lp:~maria-captains/maria/5.1-converting
- maria-pbxt-1009g
- Merge into 5.1-converting
Proposed by
Paul McCullagh
Status: | Merged |
---|---|
Approved by: | Kristian Nielsen |
Approved revision: | not available |
Merged at revision: | not available |
Proposed branch: | lp:~paul-mccullagh/maria/maria-pbxt-1009g |
Merge into: | lp:~maria-captains/maria/5.1-converting |
Diff against target: |
268 lines (+66/-52) 4 files modified
storage/pbxt/ChangeLog (+4/-0) storage/pbxt/src/discover_xt.cc (+2/-2) storage/pbxt/src/ha_pbxt.cc (+59/-49) storage/pbxt/src/strutil_xt.cc (+1/-1) |
To merge this branch: | bzr merge lp:~paul-mccullagh/maria/maria-pbxt-1009g |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Kristian Nielsen | Approve | ||
Review via email: mp+16636@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
Revision history for this message
Paul McCullagh (paul-mccullagh) wrote : | # |
Revision history for this message
Kristian Nielsen (knielsen) wrote : | # |
Merged into lp:~maria-captains/maria/5.1-release (will later be merged into lp:maria).
Thanks!
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'storage/pbxt/ChangeLog' | |||
2 | --- storage/pbxt/ChangeLog 2009-12-01 09:50:46 +0000 | |||
3 | +++ storage/pbxt/ChangeLog 2009-12-29 10:54:19 +0000 | |||
4 | @@ -1,6 +1,10 @@ | |||
5 | 1 | PBXT Release Notes | 1 | PBXT Release Notes |
6 | 2 | ================== | 2 | ================== |
7 | 3 | 3 | ||
8 | 4 | ------- 1.0.09g RC3 - 2009-12-16 | ||
9 | 5 | |||
10 | 6 | RN292: Fixed a bug that resulted in 2-phase commit not being used between PBXT and the binlog. This bug was a result of a hack which as added to solve a problem in an pre-release version of MySQL 5.1. The hack was removed. | ||
11 | 7 | |||
12 | 4 | ------- 1.0.09f RC3 - 2009-11-30 | 8 | ------- 1.0.09f RC3 - 2009-11-30 |
13 | 5 | 9 | ||
14 | 6 | RN291: Fixed bug #489088: On shutdown MySQL reports: [Warning] Plugin 'PBXT' will be forced to shutdown. | 10 | RN291: Fixed bug #489088: On shutdown MySQL reports: [Warning] Plugin 'PBXT' will be forced to shutdown. |
15 | 7 | 11 | ||
16 | === modified file 'storage/pbxt/src/discover_xt.cc' | |||
17 | --- storage/pbxt/src/discover_xt.cc 2009-12-16 08:13:18 +0000 | |||
18 | +++ storage/pbxt/src/discover_xt.cc 2009-12-29 10:54:19 +0000 | |||
19 | @@ -355,10 +355,10 @@ | |||
20 | 355 | { | 355 | { |
21 | 356 | if (!(b_flags & HA_NOSAME)) | 356 | if (!(b_flags & HA_NOSAME)) |
22 | 357 | return -1; | 357 | return -1; |
24 | 358 | if ((a_flags ^ b_flags) & (HA_NULL_PART_KEY | HA_END_SPACE_KEY)) | 358 | if ((a_flags ^ b_flags) & HA_NULL_PART_KEY) |
25 | 359 | { | 359 | { |
26 | 360 | /* Sort NOT NULL keys before other keys */ | 360 | /* Sort NOT NULL keys before other keys */ |
28 | 361 | return (a_flags & (HA_NULL_PART_KEY | HA_END_SPACE_KEY)) ? 1 : -1; | 361 | return (a_flags & HA_NULL_PART_KEY) ? 1 : -1; |
29 | 362 | } | 362 | } |
30 | 363 | if (a->name == primary_key_name) | 363 | if (a->name == primary_key_name) |
31 | 364 | return -1; | 364 | return -1; |
32 | 365 | 365 | ||
33 | === modified file 'storage/pbxt/src/ha_pbxt.cc' | |||
34 | --- storage/pbxt/src/ha_pbxt.cc 2009-11-27 15:37:02 +0000 | |||
35 | +++ storage/pbxt/src/ha_pbxt.cc 2009-12-29 10:54:19 +0000 | |||
36 | @@ -1442,7 +1442,7 @@ | |||
37 | 1442 | XTThreadPtr self; | 1442 | XTThreadPtr self; |
38 | 1443 | 1443 | ||
39 | 1444 | if ((self = (XTThreadPtr) *thd_ha_data(thd, hton))) { | 1444 | if ((self = (XTThreadPtr) *thd_ha_data(thd, hton))) { |
41 | 1445 | XT_PRINT1(self, "pbxt_commit all=%d\n", all); | 1445 | XT_PRINT2(self, "%s pbxt_commit all=%d\n", all ? "END CONN XACT" : "END STAT", all); |
42 | 1446 | 1446 | ||
43 | 1447 | if (self->st_xact_data) { | 1447 | if (self->st_xact_data) { |
44 | 1448 | /* There are no table locks, commit immediately in all cases | 1448 | /* There are no table locks, commit immediately in all cases |
45 | @@ -1474,7 +1474,7 @@ | |||
46 | 1474 | XTThreadPtr self; | 1474 | XTThreadPtr self; |
47 | 1475 | 1475 | ||
48 | 1476 | if ((self = (XTThreadPtr) *thd_ha_data(thd, hton))) { | 1476 | if ((self = (XTThreadPtr) *thd_ha_data(thd, hton))) { |
50 | 1477 | XT_PRINT1(self, "pbxt_rollback all=%d in pbxt_commit\n", all); | 1477 | XT_PRINT2(self, "%s pbxt_rollback all=%d\n", all ? "CONN END XACT" : "STAT END", all); |
51 | 1478 | 1478 | ||
52 | 1479 | if (self->st_xact_data) { | 1479 | if (self->st_xact_data) { |
53 | 1480 | /* There are no table locks, rollback immediately in all cases | 1480 | /* There are no table locks, rollback immediately in all cases |
54 | @@ -1538,7 +1538,7 @@ | |||
55 | 1538 | * except when this is a statement commit with an explicit | 1538 | * except when this is a statement commit with an explicit |
56 | 1539 | * transaction (!all && !self->st_auto_commit). | 1539 | * transaction (!all && !self->st_auto_commit). |
57 | 1540 | */ | 1540 | */ |
59 | 1541 | if (all) { | 1541 | if (all || self->st_auto_commit) { |
60 | 1542 | XID xid; | 1542 | XID xid; |
61 | 1543 | 1543 | ||
62 | 1544 | XT_PRINT0(self, "xt_xn_prepare in pbxt_prepare\n"); | 1544 | XT_PRINT0(self, "xt_xn_prepare in pbxt_prepare\n"); |
63 | @@ -2620,26 +2620,7 @@ | |||
64 | 2620 | } | 2620 | } |
65 | 2621 | #endif | 2621 | #endif |
66 | 2622 | 2622 | ||
87 | 2623 | /* GOTCHA: I have a huge problem with the transaction statement. | 2623 | /* {START-STAT-HACK} previously position of start statement hack. */ |
68 | 2624 | * It is not ALWAYS committed (I mean ha_commit_trans() is | ||
69 | 2625 | * not always called - for example in SELECT). | ||
70 | 2626 | * | ||
71 | 2627 | * If I call trans_register_ha() but ha_commit_trans() is not called | ||
72 | 2628 | * then MySQL thinks a transaction is still running (while | ||
73 | 2629 | * I have committed the auto-transaction in ha_pbxt::external_lock()). | ||
74 | 2630 | * | ||
75 | 2631 | * This causes all kinds of problems, like transactions | ||
76 | 2632 | * are killed when they should not be. | ||
77 | 2633 | * | ||
78 | 2634 | * To prevent this, I only inform MySQL that a transaction | ||
79 | 2635 | * has beens started when an update is performed. I have determined that | ||
80 | 2636 | * ha_commit_trans() is only guarenteed to be called if an update is done. | ||
81 | 2637 | */ | ||
82 | 2638 | if (!pb_open_tab->ot_thread->st_stat_trans) { | ||
83 | 2639 | trans_register_ha(pb_mysql_thd, FALSE, pbxt_hton); | ||
84 | 2640 | XT_PRINT0(pb_open_tab->ot_thread, "ha_pbxt::write_row trans_register_ha all=FALSE\n"); | ||
85 | 2641 | pb_open_tab->ot_thread->st_stat_trans = TRUE; | ||
86 | 2642 | } | ||
88 | 2643 | 2624 | ||
89 | 2644 | xt_xlog_check_long_writer(pb_open_tab->ot_thread); | 2625 | xt_xlog_check_long_writer(pb_open_tab->ot_thread); |
90 | 2645 | 2626 | ||
91 | @@ -2730,11 +2711,7 @@ | |||
92 | 2730 | XT_DISABLED_TRACE(("UPDATE tx=%d val=%d\n", (int) self->st_xact_data->xd_start_xn_id, (int) XT_GET_DISK_4(&new_data[1]))); | 2711 | XT_DISABLED_TRACE(("UPDATE tx=%d val=%d\n", (int) self->st_xact_data->xd_start_xn_id, (int) XT_GET_DISK_4(&new_data[1]))); |
93 | 2731 | //statistic_increment(ha_update_count,&LOCK_status); | 2712 | //statistic_increment(ha_update_count,&LOCK_status); |
94 | 2732 | 2713 | ||
100 | 2733 | if (!self->st_stat_trans) { | 2714 | /* {START-STAT-HACK} previously position of start statement hack. */ |
96 | 2734 | trans_register_ha(pb_mysql_thd, FALSE, pbxt_hton); | ||
97 | 2735 | XT_PRINT0(self, "ha_pbxt::update_row trans_register_ha all=FALSE\n"); | ||
98 | 2736 | self->st_stat_trans = TRUE; | ||
99 | 2737 | } | ||
101 | 2738 | 2715 | ||
102 | 2739 | xt_xlog_check_long_writer(self); | 2716 | xt_xlog_check_long_writer(self); |
103 | 2740 | 2717 | ||
104 | @@ -2821,11 +2798,7 @@ | |||
105 | 2821 | } | 2798 | } |
106 | 2822 | #endif | 2799 | #endif |
107 | 2823 | 2800 | ||
113 | 2824 | if (!pb_open_tab->ot_thread->st_stat_trans) { | 2801 | /* {START-STAT-HACK} previously position of start statement hack. */ |
109 | 2825 | trans_register_ha(pb_mysql_thd, FALSE, pbxt_hton); | ||
110 | 2826 | XT_PRINT0(pb_open_tab->ot_thread, "ha_pbxt::delete_row trans_register_ha all=FALSE\n"); | ||
111 | 2827 | pb_open_tab->ot_thread->st_stat_trans = TRUE; | ||
112 | 2828 | } | ||
114 | 2829 | 2802 | ||
115 | 2830 | xt_xlog_check_long_writer(pb_open_tab->ot_thread); | 2803 | xt_xlog_check_long_writer(pb_open_tab->ot_thread); |
116 | 2831 | 2804 | ||
117 | @@ -3155,15 +3128,12 @@ | |||
118 | 3155 | 3128 | ||
119 | 3156 | printf("index_init %s index %d cols req=%d/%d read_bits=%X write_bits=%X index_bits=%X\n", pb_open_tab->ot_table->tab_name->ps_path, (int) idx, pb_open_tab->ot_cols_req, pb_open_tab->ot_cols_req, (int) *table->read_set->bitmap, (int) *table->write_set->bitmap, (int) *ind->mi_col_map.bitmap); | 3129 | printf("index_init %s index %d cols req=%d/%d read_bits=%X write_bits=%X index_bits=%X\n", pb_open_tab->ot_table->tab_name->ps_path, (int) idx, pb_open_tab->ot_cols_req, pb_open_tab->ot_cols_req, (int) *table->read_set->bitmap, (int) *table->write_set->bitmap, (int) *ind->mi_col_map.bitmap); |
120 | 3157 | #endif | 3130 | #endif |
121 | 3131 | /* {START-STAT-HACK} previously position of start statement hack, | ||
122 | 3132 | * previous comment to code below: */ | ||
123 | 3158 | /* Start a statement based transaction as soon | 3133 | /* Start a statement based transaction as soon |
124 | 3159 | * as a read is done for a modify type statement! | 3134 | * as a read is done for a modify type statement! |
125 | 3160 | * Previously, this was done too late! | 3135 | * Previously, this was done too late! |
126 | 3161 | */ | 3136 | */ |
127 | 3162 | if (!thread->st_stat_trans) { | ||
128 | 3163 | trans_register_ha(pb_mysql_thd, FALSE, pbxt_hton); | ||
129 | 3164 | XT_PRINT0(thread, "ha_pbxt::update_row trans_register_ha all=FALSE\n"); | ||
130 | 3165 | thread->st_stat_trans = TRUE; | ||
131 | 3166 | } | ||
132 | 3167 | } | 3137 | } |
133 | 3168 | else { | 3138 | else { |
134 | 3169 | pb_open_tab->ot_cols_req = ha_get_max_bit(table->read_set); | 3139 | pb_open_tab->ot_cols_req = ha_get_max_bit(table->read_set); |
135 | @@ -3612,15 +3582,12 @@ | |||
136 | 3612 | /* The number of columns required: */ | 3582 | /* The number of columns required: */ |
137 | 3613 | if (pb_open_tab->ot_is_modify) { | 3583 | if (pb_open_tab->ot_is_modify) { |
138 | 3614 | pb_open_tab->ot_cols_req = table->read_set->MX_BIT_SIZE(); | 3584 | pb_open_tab->ot_cols_req = table->read_set->MX_BIT_SIZE(); |
139 | 3585 | /* {START-STAT-HACK} previously position of start statement hack, | ||
140 | 3586 | * previous comment to code below: */ | ||
141 | 3615 | /* Start a statement based transaction as soon | 3587 | /* Start a statement based transaction as soon |
142 | 3616 | * as a read is done for a modify type statement! | 3588 | * as a read is done for a modify type statement! |
143 | 3617 | * Previously, this was done too late! | 3589 | * Previously, this was done too late! |
144 | 3618 | */ | 3590 | */ |
145 | 3619 | if (!thread->st_stat_trans) { | ||
146 | 3620 | trans_register_ha(pb_mysql_thd, FALSE, pbxt_hton); | ||
147 | 3621 | XT_PRINT0(thread, "ha_pbxt::update_row trans_register_ha all=FALSE\n"); | ||
148 | 3622 | thread->st_stat_trans = TRUE; | ||
149 | 3623 | } | ||
150 | 3624 | } | 3591 | } |
151 | 3625 | else { | 3592 | else { |
152 | 3626 | pb_open_tab->ot_cols_req = ha_get_max_bit(table->read_set); | 3593 | pb_open_tab->ot_cols_req = ha_get_max_bit(table->read_set); |
153 | @@ -4631,7 +4598,7 @@ | |||
154 | 4631 | cont_(b); | 4598 | cont_(b); |
155 | 4632 | } | 4599 | } |
156 | 4633 | 4600 | ||
158 | 4634 | /* See (***) */ | 4601 | /* See {IS-UPDATE-STAT} */ |
159 | 4635 | self->st_is_update = FALSE; | 4602 | self->st_is_update = FALSE; |
160 | 4636 | 4603 | ||
161 | 4637 | /* Auto begin a transaction (if one is not already running): */ | 4604 | /* Auto begin a transaction (if one is not already running): */ |
162 | @@ -4660,7 +4627,7 @@ | |||
163 | 4660 | } | 4627 | } |
164 | 4661 | 4628 | ||
165 | 4662 | /* | 4629 | /* |
167 | 4663 | * (**) GOTCHA: trans_register_ha() is not mentioned in the documentation. | 4630 | * {START-TRANS} GOTCHA: trans_register_ha() is not mentioned in the documentation. |
168 | 4664 | * It must be called to inform MySQL that we have a transaction (see start_stmt). | 4631 | * It must be called to inform MySQL that we have a transaction (see start_stmt). |
169 | 4665 | * | 4632 | * |
170 | 4666 | * Here are some tests that confirm whether things are done correctly: | 4633 | * Here are some tests that confirm whether things are done correctly: |
171 | @@ -4698,10 +4665,46 @@ | |||
172 | 4698 | */ | 4665 | */ |
173 | 4699 | if (!self->st_auto_commit) { | 4666 | if (!self->st_auto_commit) { |
174 | 4700 | trans_register_ha(thd, TRUE, pbxt_hton); | 4667 | trans_register_ha(thd, TRUE, pbxt_hton); |
176 | 4701 | XT_PRINT0(self, "ha_pbxt::external_lock trans_register_ha all=TRUE\n"); | 4668 | XT_PRINT0(self, "CONN START XACT - ha_pbxt::external_lock --> trans_register_ha\n"); |
177 | 4702 | } | 4669 | } |
178 | 4703 | } | 4670 | } |
179 | 4704 | 4671 | ||
180 | 4672 | /* Start a statment transaction: */ | ||
181 | 4673 | /* {START-STAT-HACK} The problem that ha_commit_trans() is not | ||
182 | 4674 | * called by MySQL seems to be fixed (tests confirm this). | ||
183 | 4675 | * Here is the previous comment when this code was execute | ||
184 | 4676 | * here {START-STAT-HACK} | ||
185 | 4677 | * | ||
186 | 4678 | * GOTCHA: I have a huge problem with the transaction statement. | ||
187 | 4679 | * It is not ALWAYS committed (I mean ha_commit_trans() is | ||
188 | 4680 | * not always called - for example in SELECT). | ||
189 | 4681 | * | ||
190 | 4682 | * If I call trans_register_ha() but ha_commit_trans() is not called | ||
191 | 4683 | * then MySQL thinks a transaction is still running (while | ||
192 | 4684 | * I have committed the auto-transaction in ha_pbxt::external_lock()). | ||
193 | 4685 | * | ||
194 | 4686 | * This causes all kinds of problems, like transactions | ||
195 | 4687 | * are killed when they should not be. | ||
196 | 4688 | * | ||
197 | 4689 | * To prevent this, I only inform MySQL that a transaction | ||
198 | 4690 | * has beens started when an update is performed. I have determined that | ||
199 | 4691 | * ha_commit_trans() is only guarenteed to be called if an update is done. | ||
200 | 4692 | * -------- | ||
201 | 4693 | * | ||
202 | 4694 | * So, this is the correct place to start a statement transaction. | ||
203 | 4695 | * | ||
204 | 4696 | * Note: if trans_register_ha() is not called before ha_write_row(), then | ||
205 | 4697 | * PBXT is not registered correctly as a modification transaction. | ||
206 | 4698 | * (mark_trx_read_write call in ha_write_row). | ||
207 | 4699 | * This leads to 2-phase commit not being called as it should when | ||
208 | 4700 | * binary logging is enabled. | ||
209 | 4701 | */ | ||
210 | 4702 | if (!pb_open_tab->ot_thread->st_stat_trans) { | ||
211 | 4703 | trans_register_ha(pb_mysql_thd, FALSE, pbxt_hton); | ||
212 | 4704 | XT_PRINT0(pb_open_tab->ot_thread, "STAT START - ha_pbxt::external_lock --> trans_register_ha\n"); | ||
213 | 4705 | pb_open_tab->ot_thread->st_stat_trans = TRUE; | ||
214 | 4706 | } | ||
215 | 4707 | |||
216 | 4705 | if (lock_type == F_WRLCK || self->st_xact_mode < XT_XACT_REPEATABLE_READ) | 4708 | if (lock_type == F_WRLCK || self->st_xact_mode < XT_XACT_REPEATABLE_READ) |
217 | 4706 | self->st_visible_time = self->st_database->db_xn_end_time; | 4709 | self->st_visible_time = self->st_database->db_xn_end_time; |
218 | 4707 | 4710 | ||
219 | @@ -4826,7 +4829,7 @@ | |||
220 | 4826 | } | 4829 | } |
221 | 4827 | } | 4830 | } |
222 | 4828 | 4831 | ||
224 | 4829 | /* (***) This is required at this level! | 4832 | /* {IS-UPDATE-STAT} This is required at this level! |
225 | 4830 | * No matter how often it is called, it is still the start of a | 4833 | * No matter how often it is called, it is still the start of a |
226 | 4831 | * statement. We need to make sure statements that are NOT mistaken | 4834 | * statement. We need to make sure statements that are NOT mistaken |
227 | 4832 | * for different type of statement. | 4835 | * for different type of statement. |
228 | @@ -4841,7 +4844,7 @@ | |||
229 | 4841 | */ | 4844 | */ |
230 | 4842 | self->st_is_update = FALSE; | 4845 | self->st_is_update = FALSE; |
231 | 4843 | 4846 | ||
233 | 4844 | /* See comment (**) */ | 4847 | /* See comment {START-TRANS} */ |
234 | 4845 | if (!self->st_xact_data) { | 4848 | if (!self->st_xact_data) { |
235 | 4846 | self->st_xact_mode = thd_tx_isolation(thd) <= ISO_READ_COMMITTED ? XT_XACT_COMMITTED_READ : XT_XACT_REPEATABLE_READ; | 4849 | self->st_xact_mode = thd_tx_isolation(thd) <= ISO_READ_COMMITTED ? XT_XACT_COMMITTED_READ : XT_XACT_REPEATABLE_READ; |
236 | 4847 | self->st_ignore_fkeys = (thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS)) != 0; | 4850 | self->st_ignore_fkeys = (thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS)) != 0; |
237 | @@ -4858,10 +4861,17 @@ | |||
238 | 4858 | } | 4861 | } |
239 | 4859 | if (!self->st_auto_commit) { | 4862 | if (!self->st_auto_commit) { |
240 | 4860 | trans_register_ha(thd, TRUE, pbxt_hton); | 4863 | trans_register_ha(thd, TRUE, pbxt_hton); |
242 | 4861 | XT_PRINT0(self, "ha_pbxt::start_stmt trans_register_ha all=TRUE\n"); | 4864 | XT_PRINT0(self, "START CONN XACT - ha_pbxt::start_stmt --> trans_register_ha\n"); |
243 | 4862 | } | 4865 | } |
244 | 4863 | } | 4866 | } |
245 | 4864 | 4867 | ||
246 | 4868 | /* Start a statment (see {START-STAT-HACK}): */ | ||
247 | 4869 | if (!pb_open_tab->ot_thread->st_stat_trans) { | ||
248 | 4870 | trans_register_ha(pb_mysql_thd, FALSE, pbxt_hton); | ||
249 | 4871 | XT_PRINT0(pb_open_tab->ot_thread, "START STAT - ha_pbxt::start_stmt --> trans_register_ha\n"); | ||
250 | 4872 | pb_open_tab->ot_thread->st_stat_trans = TRUE; | ||
251 | 4873 | } | ||
252 | 4874 | |||
253 | 4865 | if (pb_open_tab->ot_for_update || self->st_xact_mode < XT_XACT_REPEATABLE_READ) | 4875 | if (pb_open_tab->ot_for_update || self->st_xact_mode < XT_XACT_REPEATABLE_READ) |
254 | 4866 | self->st_visible_time = self->st_database->db_xn_end_time; | 4876 | self->st_visible_time = self->st_database->db_xn_end_time; |
255 | 4867 | 4877 | ||
256 | 4868 | 4878 | ||
257 | === modified file 'storage/pbxt/src/strutil_xt.cc' | |||
258 | --- storage/pbxt/src/strutil_xt.cc 2009-11-24 10:55:06 +0000 | |||
259 | +++ storage/pbxt/src/strutil_xt.cc 2009-12-29 10:54:19 +0000 | |||
260 | @@ -380,7 +380,7 @@ | |||
261 | 380 | /* Version number must also be set in configure.in! */ | 380 | /* Version number must also be set in configure.in! */ |
262 | 381 | xtPublic c_char *xt_get_version(void) | 381 | xtPublic c_char *xt_get_version(void) |
263 | 382 | { | 382 | { |
265 | 383 | return "1.0.09f RC"; | 383 | return "1.0.09g RC"; |
266 | 384 | } | 384 | } |
267 | 385 | 385 | ||
268 | 386 | /* Copy and URL decode! */ | 386 | /* Copy and URL decode! */ |
This patch fixes a bug that resulted in 2-phase commit not being used between PBXT and the binlog. This bug was a result of a hack which as added to solve a problem in an pre-release version of MySQL 5.1. The hack was removed.