Merge lp:~vkolesnikov/pbxt/pbxt-bug-378222 into lp:pbxt

Proposed by Vladimir Kolesnikov
Status: Merged
Merged at revision: not available
Proposed branch: lp:~vkolesnikov/pbxt/pbxt-bug-378222
Merge into: lp:pbxt
Diff against target: None lines
To merge this branch: bzr merge lp:~vkolesnikov/pbxt/pbxt-bug-378222
Reviewer Review Type Date Requested Status
PBXT Core Pending
Review via email: mp+7376@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Paul McCullagh (paul-mccullagh) wrote :

Hi Vlad,

This patch looks good. Just one thing: how about doing this in
xt_tab_init_db()?

I think this would be more efficient.

On Jun 12, 2009, at 4:40 PM, Vladimir Kolesnikov wrote:

> === modified file 'src/database_xt.cc'
> --- src/database_xt.cc 2009-05-28 15:17:16 +0000
> +++ src/database_xt.cc 2009-06-12 14:29:30 +0000
> @@ -616,7 +616,9 @@
> xtPublic void xt_open_database(XTThreadPtr self, char *path, xtBool
> multi_path)
> {
> XTDatabaseHPtr db;
> -
> + XTTableDescRec desc;
> + XTPathStr table_path;
> +
> /* We cannot get a database, without unusing the current
> * first. The reason is that the restart process will
> * partially set the current database!
> @@ -625,7 +627,18 @@
> db = xt_get_database(self, path, multi_path);
> pushr_(xt_heap_release, db);
> xt_use_database(self, db, XT_FOR_USER);
> - freer_(); // xt_heap_release(self, db);
> +
> + xt_describe_tables_init(self, db, &desc);
> + pushr_(xt_describe_tables_exit, &desc);
> + while (xt_describe_tables_next(self, &desc)) {
> + xt_strcpy(PATH_MAX, table_path.ps_path, desc.td_tab_path->tp_path);
> + xt_add_dir_char(PATH_MAX, table_path.ps_path);
> + xt_strcat(PATH_MAX, table_path.ps_path, desc.td_tab_name);
> + xt_heap_release(self, xt_use_table(self, &table_path, FALSE,
> FALSE, NULL));
> + }
> +
> + freer_(); // xt_describe_tables_exit(self, desc);
> + freer_(); // xt_heap_release(self, db);
> }
>

--
Paul McCullagh
PrimeBase Technologies
www.primebase.org
www.blobstreaming.org
pbxt.blogspot.com

Revision history for this message
Vladimir Kolesnikov (vkolesnikov) wrote :

This was my first idea too, but xt_use_table requires self->st_database
to be inited which is done in xt_ue_database() so I put this code right
after the call to xt_use_database (and xt_use_database itself doesn't
seem to be good place too). Of course I can copy some code from
xt_use_database and put it before the use_table but I thought it's not a
good idea.

Paul McCullagh wrote:
> Hi Vlad,
>
> This patch looks good. Just one thing: how about doing this in
> xt_tab_init_db()?
>
> I think this would be more efficient.
>
> On Jun 12, 2009, at 4:40 PM, Vladimir Kolesnikov wrote:
>
>
>> === modified file 'src/database_xt.cc'
>> --- src/database_xt.cc 2009-05-28 15:17:16 +0000
>> +++ src/database_xt.cc 2009-06-12 14:29:30 +0000
>> @@ -616,7 +616,9 @@
>> xtPublic void xt_open_database(XTThreadPtr self, char *path, xtBool
>> multi_path)
>> {
>> XTDatabaseHPtr db;
>> -
>> + XTTableDescRec desc;
>> + XTPathStr table_path;
>> +
>> /* We cannot get a database, without unusing the current
>> * first. The reason is that the restart process will
>> * partially set the current database!
>> @@ -625,7 +627,18 @@
>> db = xt_get_database(self, path, multi_path);
>> pushr_(xt_heap_release, db);
>> xt_use_database(self, db, XT_FOR_USER);
>> - freer_(); // xt_heap_release(self, db);
>> +
>> + xt_describe_tables_init(self, db, &desc);
>> + pushr_(xt_describe_tables_exit, &desc);
>> + while (xt_describe_tables_next(self, &desc)) {
>> + xt_strcpy(PATH_MAX, table_path.ps_path, desc.td_tab_path->tp_path);
>> + xt_add_dir_char(PATH_MAX, table_path.ps_path);
>> + xt_strcat(PATH_MAX, table_path.ps_path, desc.td_tab_name);
>> + xt_heap_release(self, xt_use_table(self, &table_path, FALSE,
>> FALSE, NULL));
>> + }
>> +
>> + freer_(); // xt_describe_tables_exit(self, desc);
>> + freer_(); // xt_heap_release(self, db);
>> }
>>
>>
>
>
>
> --
> Paul McCullagh
> PrimeBase Technologies
> www.primebase.org
> www.blobstreaming.org
> pbxt.blogspot.com
>
>
>
>

--
--
Best Regards,
Vladimir

Revision history for this message
Paul McCullagh (paul-mccullagh) wrote :

I think you could try: xt_use_table_no_lock()

Because lock on db->db_tables is not required anyway.

On Jun 16, 2009, at 12:18 PM, Vladimir Kolesnikov wrote:

> This was my first idea too, but xt_use_table requires self-
> >st_database
> to be inited which is done in xt_ue_database() so I put this code
> right
> after the call to xt_use_database (and xt_use_database itself doesn't
> seem to be good place too). Of course I can copy some code from
> xt_use_database and put it before the use_table but I thought it's
> not a
> good idea.
>
> Paul McCullagh wrote:
>> Hi Vlad,
>>
>> This patch looks good. Just one thing: how about doing this in
>> xt_tab_init_db()?
>>
>> I think this would be more efficient.
>>
>> On Jun 12, 2009, at 4:40 PM, Vladimir Kolesnikov wrote:
>>
>>
>>> === modified file 'src/database_xt.cc'
>>> --- src/database_xt.cc 2009-05-28 15:17:16 +0000
>>> +++ src/database_xt.cc 2009-06-12 14:29:30 +0000
>>> @@ -616,7 +616,9 @@
>>> xtPublic void xt_open_database(XTThreadPtr self, char *path, xtBool
>>> multi_path)
>>> {
>>> XTDatabaseHPtr db;
>>> -
>>> + XTTableDescRec desc;
>>> + XTPathStr table_path;
>>> +
>>> /* We cannot get a database, without unusing the current
>>> * first. The reason is that the restart process will
>>> * partially set the current database!
>>> @@ -625,7 +627,18 @@
>>> db = xt_get_database(self, path, multi_path);
>>> pushr_(xt_heap_release, db);
>>> xt_use_database(self, db, XT_FOR_USER);
>>> - freer_(); // xt_heap_release(self, db);
>>> +
>>> + xt_describe_tables_init(self, db, &desc);
>>> + pushr_(xt_describe_tables_exit, &desc);
>>> + while (xt_describe_tables_next(self, &desc)) {
>>> + xt_strcpy(PATH_MAX, table_path.ps_path, desc.td_tab_path-
>>> >tp_path);
>>> + xt_add_dir_char(PATH_MAX, table_path.ps_path);
>>> + xt_strcat(PATH_MAX, table_path.ps_path, desc.td_tab_name);
>>> + xt_heap_release(self, xt_use_table(self, &table_path, FALSE,
>>> FALSE, NULL));
>>> + }
>>> +
>>> + freer_(); // xt_describe_tables_exit(self, desc);
>>> + freer_(); // xt_heap_release(self, db);
>>> }
>>>
>>>
>>
>>
>>
>> --
>> Paul McCullagh
>> PrimeBase Technologies
>> www.primebase.org
>> www.blobstreaming.org
>> pbxt.blogspot.com
>>
>>
>>
>>
>
>
> --
> --
> Best Regards,
> Vladimir
>
> https://code.launchpad.net/~vkolesnikov/pbxt/pbxt-bug-378222/+merge/
> 7376
> Your team PBXT Core is subscribed to branch lp:pbxt.

--
Paul McCullagh
PrimeBase Technologies
www.primebase.org
www.blobstreaming.org
pbxt.blogspot.com

Revision history for this message
Vladimir Kolesnikov (vkolesnikov) wrote :

pushed the change

Paul McCullagh wrote:
> I think you could try: xt_use_table_no_lock()
>
> Because lock on db->db_tables is not required anyway.
>
> On Jun 16, 2009, at 12:18 PM, Vladimir Kolesnikov wrote:
>
>
>> This was my first idea too, but xt_use_table requires self-
>>
>>> st_database
>>>
>> to be inited which is done in xt_ue_database() so I put this code
>> right
>> after the call to xt_use_database (and xt_use_database itself doesn't
>> seem to be good place too). Of course I can copy some code from
>> xt_use_database and put it before the use_table but I thought it's
>> not a
>> good idea.
>>
>> Paul McCullagh wrote:
>>
>>> Hi Vlad,
>>>
>>> This patch looks good. Just one thing: how about doing this in
>>> xt_tab_init_db()?
>>>
>>> I think this would be more efficient.
>>>
>>> On Jun 12, 2009, at 4:40 PM, Vladimir Kolesnikov wrote:
>>>
>>>
>>>
>>>> === modified file 'src/database_xt.cc'
>>>> --- src/database_xt.cc 2009-05-28 15:17:16 +0000
>>>> +++ src/database_xt.cc 2009-06-12 14:29:30 +0000
>>>> @@ -616,7 +616,9 @@
>>>> xtPublic void xt_open_database(XTThreadPtr self, char *path, xtBool
>>>> multi_path)
>>>> {
>>>> XTDatabaseHPtr db;
>>>> -
>>>> + XTTableDescRec desc;
>>>> + XTPathStr table_path;
>>>> +
>>>> /* We cannot get a database, without unusing the current
>>>> * first. The reason is that the restart process will
>>>> * partially set the current database!
>>>> @@ -625,7 +627,18 @@
>>>> db = xt_get_database(self, path, multi_path);
>>>> pushr_(xt_heap_release, db);
>>>> xt_use_database(self, db, XT_FOR_USER);
>>>> - freer_(); // xt_heap_release(self, db);
>>>> +
>>>> + xt_describe_tables_init(self, db, &desc);
>>>> + pushr_(xt_describe_tables_exit, &desc);
>>>> + while (xt_describe_tables_next(self, &desc)) {
>>>> + xt_strcpy(PATH_MAX, table_path.ps_path, desc.td_tab_path-
>>>>
>>>>> tp_path);
>>>>>
>>>> + xt_add_dir_char(PATH_MAX, table_path.ps_path);
>>>> + xt_strcat(PATH_MAX, table_path.ps_path, desc.td_tab_name);
>>>> + xt_heap_release(self, xt_use_table(self, &table_path, FALSE,
>>>> FALSE, NULL));
>>>> + }
>>>> +
>>>> + freer_(); // xt_describe_tables_exit(self, desc);
>>>> + freer_(); // xt_heap_release(self, db);
>>>> }
>>>>
>>>>
>>>>
>>>
>>> --
>>> Paul McCullagh
>>> PrimeBase Technologies
>>> www.primebase.org
>>> www.blobstreaming.org
>>> pbxt.blogspot.com
>>>
>>>
>>>
>>>
>>>
>> --
>> --
>> Best Regards,
>> Vladimir
>>
>> https://code.launchpad.net/~vkolesnikov/pbxt/pbxt-bug-378222/+merge/
>> 7376
>> Your team PBXT Core is subscribed to branch lp:pbxt.
>>
>
>
>
> --
> Paul McCullagh
> PrimeBase Technologies
> www.primebase.org
> www.blobstreaming.org
> pbxt.blogspot.com
>
>
>
>

--
--
Best Regards,
Vladimir

lp:~vkolesnikov/pbxt/pbxt-bug-378222 updated
658. By Paul McCullagh

Merged RN246

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'ChangeLog'
2--- ChangeLog 2009-06-10 16:26:33 +0000
3+++ ChangeLog 2009-06-12 14:29:30 +0000
4@@ -3,6 +3,8 @@
5
6 ------- 1.0.08 RC - Not yet released
7
8+RN246: Fixed bug #378222: Drop sakila causes error: Cannot delete or update a parent row: a foreign key constraint fails
9+
10 RN245: Fixed bug #379315: Inconsistent behavior of DELETE IGNORE and FK constraint
11
12 RN244: Fixed a recovery problem: during the recovery of "record modified" action the table was updated before the old index entries were removed; then the xres_remove_index_entries was supplied the new record which lead to incorrect index update
13
14=== modified file 'src/database_xt.cc'
15--- src/database_xt.cc 2009-05-28 15:17:16 +0000
16+++ src/database_xt.cc 2009-06-12 14:29:30 +0000
17@@ -616,7 +616,9 @@
18 xtPublic void xt_open_database(XTThreadPtr self, char *path, xtBool multi_path)
19 {
20 XTDatabaseHPtr db;
21-
22+ XTTableDescRec desc;
23+ XTPathStr table_path;
24+
25 /* We cannot get a database, without unusing the current
26 * first. The reason is that the restart process will
27 * partially set the current database!
28@@ -625,7 +627,18 @@
29 db = xt_get_database(self, path, multi_path);
30 pushr_(xt_heap_release, db);
31 xt_use_database(self, db, XT_FOR_USER);
32- freer_(); // xt_heap_release(self, db);
33+
34+ xt_describe_tables_init(self, db, &desc);
35+ pushr_(xt_describe_tables_exit, &desc);
36+ while (xt_describe_tables_next(self, &desc)) {
37+ xt_strcpy(PATH_MAX, table_path.ps_path, desc.td_tab_path->tp_path);
38+ xt_add_dir_char(PATH_MAX, table_path.ps_path);
39+ xt_strcat(PATH_MAX, table_path.ps_path, desc.td_tab_name);
40+ xt_heap_release(self, xt_use_table(self, &table_path, FALSE, FALSE, NULL));
41+ }
42+
43+ freer_(); // xt_describe_tables_exit(self, desc);
44+ freer_(); // xt_heap_release(self, db);
45 }
46
47 /* This function can only be called if you do not already have a database in
48
49=== modified file 'src/datadic_xt.cc'
50--- src/datadic_xt.cc 2009-05-19 15:22:26 +0000
51+++ src/datadic_xt.cc 2009-06-12 14:29:30 +0000
52@@ -650,7 +650,7 @@
53 int parseKeyAction(XTThreadPtr self);
54 void parseCreateTable(XTThreadPtr self);
55 void parseAddTableItem(XTThreadPtr self);
56- void parseQualifiedName(XTThreadPtr self, char *name);
57+ void parseQualifiedName(XTThreadPtr self, char *parent_name, char *name);
58 void parseTableName(XTThreadPtr self, bool alterTable);
59 void parseExpression(XTThreadPtr self, bool allow_reserved);
60 void parseBrackets(XTThreadPtr self);
61@@ -720,7 +720,7 @@
62 }
63 virtual void addListedColumn(XTThreadPtr XT_UNUSED(self), char *XT_UNUSED(index_col_name)) {
64 }
65- virtual void setReferencedTable(XTThreadPtr XT_UNUSED(self), char *XT_UNUSED(ref_table)) {
66+ virtual void setReferencedTable(XTThreadPtr XT_UNUSED(self), char *XT_UNUSED(ref_schema), char *XT_UNUSED(ref_table)) {
67 }
68 virtual void addReferencedColumn(XTThreadPtr XT_UNUSED(self), char *XT_UNUSED(index_col_name)) {
69 }
70@@ -870,7 +870,7 @@
71 if (pt_current->isKeyWord("CONSTRAINT")) {
72 pt_current = pt_tokenizer->nextToken(self);
73 if (pt_current->isIdentifier())
74- parseQualifiedName(self, name);
75+ parseQualifiedName(self, NULL, name);
76 }
77
78 if (pt_current->isReservedWord(XT_TK_PRIMARY)) {
79@@ -985,13 +985,15 @@
80 char name[XT_IDENTIFIER_NAME_SIZE];
81
82 pt_current = pt_tokenizer->nextToken(self);
83- parseQualifiedName(self, name);
84+ parseQualifiedName(self, NULL, name);
85 moveColumn(self, name);
86 }
87 }
88
89-void XTParseTable::parseQualifiedName(XTThreadPtr self, char *name)
90+void XTParseTable::parseQualifiedName(XTThreadPtr self, char *parent_name, char *name)
91 {
92+ if (parent_name)
93+ parent_name[0] = '\0';
94 /* Should be an identifier by I have this example:
95 * CREATE TABLE t1 ( comment CHAR(32) ASCII NOT NULL, koi8_ru_f CHAR(32) CHARACTER SET koi8r NOT NULL default '' ) CHARSET=latin5;
96 *
97@@ -1001,6 +1003,8 @@
98 raiseError(self, pt_current, XT_ERR_ID_TOO_LONG);
99 pt_current = pt_tokenizer->nextToken(self);
100 while (pt_current->isKeyWord(".")) {
101+ if (parent_name)
102+ xt_strcpy(XT_IDENTIFIER_NAME_SIZE,parent_name, name);
103 pt_current = pt_tokenizer->nextToken(self);
104 /* Accept anything after the DOT! */
105 if (pt_current->getString(name, XT_IDENTIFIER_NAME_SIZE) >= XT_IDENTIFIER_NAME_SIZE)
106@@ -1013,7 +1017,7 @@
107 {
108 char name[XT_IDENTIFIER_NAME_SIZE];
109
110- parseQualifiedName(self, name);
111+ parseQualifiedName(self, NULL, name);
112 setTableName(self, name, alterTable);
113 }
114
115@@ -1022,7 +1026,7 @@
116 char col_name[XT_IDENTIFIER_NAME_SIZE];
117
118 // column_definition
119- parseQualifiedName(self, col_name);
120+ parseQualifiedName(self, NULL, col_name);
121 addColumn(self, col_name, old_col_name);
122 parseDataType(self);
123
124@@ -1122,7 +1126,7 @@
125 pt_current->expectKeyWord(self, "(");
126 do {
127 pt_current = pt_tokenizer->nextToken(self);
128- parseQualifiedName(self, name);
129+ parseQualifiedName(self, NULL, name);
130 addListedColumn(self, name);
131 cols++;
132 if (index_cols) {
133@@ -1146,19 +1150,20 @@
134 int on_delete = XT_KEY_ACTION_DEFAULT;
135 int on_update = XT_KEY_ACTION_DEFAULT;
136 char name[XT_IDENTIFIER_NAME_SIZE];
137+ char parent_name[XT_IDENTIFIER_NAME_SIZE];
138 u_int cols = 0;
139
140 // REFERENCES tbl_name
141 pt_current = pt_tokenizer->nextToken(self, "REFERENCES", pt_current);
142- parseQualifiedName(self, name);
143- setReferencedTable(self, name);
144+ parseQualifiedName(self, parent_name, name);
145+ setReferencedTable(self, parent_name[0] ? parent_name : NULL, name);
146
147 // [ (index_col_name,...) ]
148 if (pt_current->isKeyWord("(")) {
149 pt_current->expectKeyWord(self, "(");
150 do {
151 pt_current = pt_tokenizer->nextToken(self);
152- parseQualifiedName(self, name);
153+ parseQualifiedName(self, NULL, name);
154 addReferencedColumn(self, name);
155 cols++;
156 if (cols > req_cols)
157@@ -1230,7 +1235,7 @@
158 if (pt_current->isReservedWord(XT_TK_COLUMN))
159 pt_current = pt_tokenizer->nextToken(self);
160
161- parseQualifiedName(self, old_col_name);
162+ parseQualifiedName(self, NULL, old_col_name);
163 parseColumnDefinition(self, old_col_name);
164 parseMoveColumn(self);
165 }
166@@ -1262,7 +1267,7 @@
167 else {
168 if (pt_current->isReservedWord(XT_TK_COLUMN))
169 pt_current = pt_tokenizer->nextToken(self);
170- parseQualifiedName(self, name);
171+ parseQualifiedName(self, NULL, name);
172 dropColumn(self, name);
173 }
174 }
175@@ -1270,7 +1275,7 @@
176 pt_current = pt_tokenizer->nextToken(self);
177 if (pt_current->isKeyWord("TO"))
178 pt_current = pt_tokenizer->nextToken(self);
179- parseQualifiedName(self, name);
180+ parseQualifiedName(self, NULL, name);
181 }
182 else
183 /* Just ignore the syntax until the next , */
184@@ -1295,7 +1300,7 @@
185 else if (pt_current->isKeyWord("SPACIAL"))
186 pt_current = pt_tokenizer->nextToken(self);
187 pt_current = pt_tokenizer->nextToken(self, "INDEX", pt_current);
188- parseQualifiedName(self, name);
189+ parseQualifiedName(self, NULL, name);
190 optionalIndexType(self);
191 pt_current = pt_tokenizer->nextToken(self, "ON", pt_current);
192 parseTableName(self, true);
193@@ -1310,7 +1315,7 @@
194
195 pt_current = pt_tokenizer->nextToken(self, "DROP", pt_current);
196 pt_current = pt_tokenizer->nextToken(self, "INDEX", pt_current);
197- parseQualifiedName(self, name);
198+ parseQualifiedName(self, NULL, name);
199 pt_current = pt_tokenizer->nextToken(self, "ON", pt_current);
200 parseTableName(self, true);
201 dropConstraint(self, name, XT_DD_INDEX);
202@@ -1351,7 +1356,7 @@
203 virtual void addConstraint(XTThreadPtr self, char *name, u_int type, bool lastColumn);
204 virtual void dropConstraint(XTThreadPtr self, char *name, u_int type);
205 virtual void addListedColumn(XTThreadPtr self, char *index_col_name);
206- virtual void setReferencedTable(XTThreadPtr self, char *ref_table);
207+ virtual void setReferencedTable(XTThreadPtr self, char *ref_schema, char *ref_table);
208 virtual void addReferencedColumn(XTThreadPtr self, char *index_col_name);
209 virtual void setActions(XTThreadPtr self, int on_delete, int on_update);
210
211@@ -1546,23 +1551,31 @@
212 }
213 }
214
215-void XTCreateTable::setReferencedTable(XTThreadPtr self, char *ref_table)
216+void XTCreateTable::setReferencedTable(XTThreadPtr self, char *ref_schema, char *ref_table)
217 {
218 XTDDForeignKey *fk = (XTDDForeignKey *) ct_curr_constraint;
219 char path[PATH_MAX];
220
221- xt_strcpy(PATH_MAX, path, ct_tab_path->ps_path);
222- xt_remove_last_name_of_path(path);
223- if (ct_convert) {
224- char buffer[XT_IDENTIFIER_NAME_SIZE];
225- size_t len;
226-
227- myxt_static_convert_identifier(self, ct_charset, ref_table, buffer, XT_IDENTIFIER_NAME_SIZE);
228- len = strlen(path);
229- myxt_static_convert_table_name(self, buffer, &path[len], PATH_MAX - len);
230- }
231- else
232+ if (ref_schema) {
233+ xt_strcpy(PATH_MAX,path, ".");
234+ xt_add_dir_char(PATH_MAX, path);
235+ xt_strcat(PATH_MAX, path, ref_schema);
236+ xt_add_dir_char(PATH_MAX, path);
237 xt_strcat(PATH_MAX, path, ref_table);
238+ } else {
239+ xt_strcpy(PATH_MAX, path, ct_tab_path->ps_path);
240+ xt_remove_last_name_of_path(path);
241+ if (ct_convert) {
242+ char buffer[XT_IDENTIFIER_NAME_SIZE];
243+ size_t len;
244+
245+ myxt_static_convert_identifier(self, ct_charset, ref_table, buffer, XT_IDENTIFIER_NAME_SIZE);
246+ len = strlen(path);
247+ myxt_static_convert_table_name(self, buffer, &path[len], PATH_MAX - len);
248+ }
249+ else
250+ xt_strcat(PATH_MAX, path, ref_table);
251+ }
252
253 fk->fk_ref_tab_name = (XTPathStrPtr) xt_dup_string(self, path);
254 }
255@@ -2065,8 +2078,13 @@
256
257 void XTDDForeignKey::loadString(XTThreadPtr self, XTStringBufferPtr sb)
258 {
259+ char schema_name[XT_IDENTIFIER_NAME_SIZE];
260+
261 XTDDConstraint::loadString(self, sb);
262 xt_sb_concat(self, sb, " REFERENCES `");
263+ xt_2nd_last_name_of_path(XT_IDENTIFIER_NAME_SIZE, schema_name, fk_ref_tab_name->ps_path);
264+ xt_sb_concat(self, sb, schema_name);
265+ xt_sb_concat(self, sb, "`.`");
266 xt_sb_concat(self, sb, xt_last_name_of_path(fk_ref_tab_name->ps_path));
267 xt_sb_concat(self, sb, "` ");
268
269@@ -2877,9 +2895,33 @@
270 return ok;
271 }
272
273-xtBool XTDDTable::checkCanDrop()
274+/*
275+ * drop_db parameter is TRUE if we are dropping the schema of this table. In this case
276+ * we return TRUE if the table has only refs to the tables from its own schema
277+ */
278+xtBool XTDDTable::checkCanDrop(xtBool drop_db)
279 {
280 /* no refs or references only itself */
281- return (dt_trefs == NULL) ||
282- ((dt_trefs->tr_next == NULL) && (dt_trefs->tr_fkey->co_table == this));
283+ if ((dt_trefs == NULL) || ((dt_trefs->tr_next == NULL) && (dt_trefs->tr_fkey->co_table == this)))
284+ return TRUE;
285+
286+ if (!drop_db)
287+ return FALSE;
288+
289+ const char *this_schema = xt_last_2_names_of_path(dt_table->tab_name->ps_path);
290+ size_t this_schema_sz = xt_last_name_of_path(dt_table->tab_name->ps_path) - this_schema;
291+ XTDDTableRef *tr = dt_trefs;
292+
293+ while (tr) {
294+ const char *tab_path = tr->tr_fkey->co_table->dt_table->tab_name->ps_path;
295+ const char *tab_schema = xt_last_2_names_of_path(tab_path);
296+ size_t tab_schema_sz = xt_last_name_of_path(tab_path) - tab_schema;
297+
298+ if (this_schema_sz != tab_schema_sz || strncmp(this_schema, tab_schema, tab_schema_sz))
299+ return FALSE;
300+
301+ tr = tr->tr_next;
302+ }
303+
304+ return TRUE;
305 }
306
307=== modified file 'src/datadic_xt.h'
308--- src/datadic_xt.h 2009-05-19 15:22:26 +0000
309+++ src/datadic_xt.h 2009-06-12 14:29:30 +0000
310@@ -288,7 +288,7 @@
311 XTDDIndex *findReferenceIndex(XTDDForeignKey *fk);
312 bool insertRow(struct XTOpenTable *rec_ot, xtWord1 *buffer);
313 bool checkNoAction(struct XTOpenTable *ot, xtRecordID rec_id);
314- xtBool checkCanDrop();
315+ xtBool checkCanDrop(xtBool drop_db);
316 bool deleteRow(struct XTOpenTable *rec_ot, xtWord1 *buffer);
317 void deleteAllRows(XTThreadPtr self);
318 bool updateRow(struct XTOpenTable *rec_ot, xtWord1 *before, xtWord1 *after);
319
320=== modified file 'src/ha_pbxt.cc'
321--- src/ha_pbxt.cc 2009-06-10 16:26:33 +0000
322+++ src/ha_pbxt.cc 2009-06-12 14:29:30 +0000
323@@ -4682,7 +4682,7 @@
324 pushr_(ha_release_exclusive_use, share);
325 ha_close_open_tables(self, share, NULL);
326
327- xt_drop_table(self, (XTPathStrPtr) table_path);
328+ xt_drop_table(self, (XTPathStrPtr) table_path, thd_sql_command(thd) == SQLCOM_DROP_DB);
329
330 freer_(); // ha_release_exclusive_use(share)
331 freer_(); // ha_unget_share(share)
332
333=== modified file 'src/table_xt.cc'
334--- src/table_xt.cc 2009-05-26 14:01:46 +0000
335+++ src/table_xt.cc 2009-06-12 14:29:30 +0000
336@@ -1590,7 +1590,7 @@
337 exit_();
338 }
339
340-xtPublic void xt_drop_table(XTThreadPtr self, XTPathStrPtr tab_name)
341+xtPublic void xt_drop_table(XTThreadPtr self, XTPathStrPtr tab_name, xtBool drop_db)
342 {
343 XTDatabaseHPtr db = self->st_database;
344 XTOpenTablePoolPtr table_pool;
345@@ -1614,7 +1614,7 @@
346 tab_id = tab->tab_id; /* tab is not null if returned table_pool is not null */
347 /* check if other tables refer this */
348 if (!self->st_ignore_fkeys)
349- can_drop = tab->tab_dic.dic_table->checkCanDrop();
350+ can_drop = tab->tab_dic.dic_table->checkCanDrop(drop_db);
351 }
352 #ifdef DRIZZLED
353 /* See the comment in ha_pbxt::delete_table regarding different implmentation of DROP TABLE
354
355=== modified file 'src/table_xt.h'
356--- src/table_xt.h 2009-05-28 15:17:16 +0000
357+++ src/table_xt.h 2009-06-12 14:29:30 +0000
358@@ -514,7 +514,7 @@
359 int xt_use_table_by_id(struct XTThread *self, XTTableHPtr *tab, struct XTDatabase *db, xtTableID tab_id);
360 XTOpenTablePtr xt_open_table(XTTableHPtr tab);
361 void xt_close_table(XTOpenTablePtr ot, xtBool flush, xtBool have_table_lock);
362-void xt_drop_table(struct XTThread *self, XTPathStrPtr name);
363+void xt_drop_table(struct XTThread *self, XTPathStrPtr name, xtBool drop_db);
364 void xt_check_table(XTThreadPtr self, XTOpenTablePtr tab);
365 void xt_rename_table(struct XTThread *self, XTPathStrPtr old_name, XTPathStrPtr new_name);
366
367
368=== modified file 'test/mysql-test/r/pbxt_bugs.result'
369--- test/mysql-test/r/pbxt_bugs.result 2009-06-10 16:26:33 +0000
370+++ test/mysql-test/r/pbxt_bugs.result 2009-06-12 14:29:30 +0000
371@@ -1230,3 +1230,25 @@
372 3
373 4
374 drop table child, parent;
375+create schema test378222;
376+use test378222;
377+create table t1 (id int primary key);
378+create table t2 (id int primary key);
379+alter table t1 add constraint foreign key (id) references t2 (id);
380+alter table t2 add constraint foreign key (id) references t1 (id);
381+drop schema test378222;
382+create schema test378222a;
383+create schema test378222b;
384+create table test378222a.t1 (id int primary key) engine = pbxt;
385+create table test378222b.t2 (id int primary key) engine = pbxt;
386+alter table test378222a.t1 add constraint foreign key (id) references test378222b.t2 (id);
387+alter table test378222b.t2 add constraint foreign key (id) references test378222a.t1 (id);
388+set foreign_key_checks = 1;
389+drop schema test378222a;
390+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails
391+drop schema test378222b;
392+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails
393+set foreign_key_checks = 0;
394+drop schema test378222a;
395+drop schema test378222b;
396+set foreign_key_checks = 1;
397
398=== modified file 'test/mysql-test/t/pbxt_bugs.test'
399--- test/mysql-test/t/pbxt_bugs.test 2009-06-10 16:26:33 +0000
400+++ test/mysql-test/t/pbxt_bugs.test 2009-06-12 14:29:30 +0000
401@@ -938,7 +938,34 @@
402
403 drop table child, parent;
404
405+# bug 378222: Drop sakila causes error: Cannot delete or update a parent row: a foreign key constraint fails
406+
407+create schema test378222;
408+use test378222;
409+create table t1 (id int primary key);
410+create table t2 (id int primary key);
411+alter table t1 add constraint foreign key (id) references t2 (id);
412+alter table t2 add constraint foreign key (id) references t1 (id);
413+drop schema test378222;
414+
415+create schema test378222a;
416+create schema test378222b;
417+create table test378222a.t1 (id int primary key) engine = pbxt;
418+create table test378222b.t2 (id int primary key) engine = pbxt;
419+alter table test378222a.t1 add constraint foreign key (id) references test378222b.t2 (id);
420+alter table test378222b.t2 add constraint foreign key (id) references test378222a.t1 (id);
421+set foreign_key_checks = 1;
422+--error 1217
423+drop schema test378222a;
424+--error 1217
425+drop schema test378222b;
426+set foreign_key_checks = 0;
427+drop schema test378222a;
428+drop schema test378222b;
429+set foreign_key_checks = 1;
430+
431 --disable_query_log
432+use test;
433 DROP TABLE t2, t5;
434 drop database pbxt;
435 --enable_query_log

Subscribers

People subscribed via source and target branches