Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
mariadb
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
mariadb
Commits
61e41ac2
Commit
61e41ac2
authored
Apr 25, 2006
by
aelkin@mysql.com
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
BUG#17263: incorrect DROP query in temporary tables replication
the fix from 5.0 with necessary modifications applied.
parent
3363effa
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
122 additions
and
39 deletions
+122
-39
sql/sql_base.cc
sql/sql_base.cc
+122
-39
No files found.
sql/sql_base.cc
View file @
61e41ac2
...
...
@@ -1167,16 +1167,26 @@ bool close_thread_table(THD *thd, TABLE **table_ptr)
}
/* close_temporary_tables' internal, 4 is due to uint4korr definition */
static
inline
uint
tmpkeyval
(
THD
*
thd
,
TABLE
*
table
)
{
return
uint4korr
(
table
->
s
->
table_cache_key
.
str
+
table
->
s
->
table_cache_key
.
length
-
4
);
}
/*
Close all temporary tables created by 'CREATE TEMPORARY TABLE' for thread
creates one DROP TEMPORARY TABLE binlog event for each pseudo-thread
*/
void
close_temporary_tables
(
THD
*
thd
)
{
TABLE
*
table
,
*
next
;
char
*
query
,
*
end
;
uint
query_buf_size
;
bool
found_user_tables
=
0
;
TABLE
*
next
,
*
prev_table
/* prev link is not maintained in TABLE's double-linked list */
,
*
table
;
char
*
query
=
(
gptr
)
0
,
*
end
;
uint
query_buf_size
,
max_names_len
;
bool
found_user_tables
;
if
(
!
thd
->
temporary_tables
)
return
;
...
...
@@ -1184,50 +1194,123 @@ void close_temporary_tables(THD *thd)
LINT_INIT
(
end
);
query_buf_size
=
50
;
// Enough for DROP ... TABLE IF EXISTS
for
(
table
=
thd
->
temporary_tables
;
table
;
table
=
table
->
next
)
/*
insertion sort of temp tables by pseudo_thread_id to build ordered list
of sublists of equal pseudo_thread_id
*/
for
(
prev_table
=
thd
->
temporary_tables
,
table
=
prev_table
->
next
,
found_user_tables
=
(
prev_table
->
s
->
table_name
.
str
[
0
]
!=
'#'
);
table
;
prev_table
=
table
,
table
=
table
->
next
)
{
TABLE
*
prev_sorted
/* same as for prev_table */
,
*
sorted
;
/*
We are going to add 4 ` around the db/table names, so 1 does not look
enough; indeed it is enough, because table->table_cache_key.length is
greater (by 8, because of server_id and thread_id) than db||table.
table not created directly by the user is moved to the tail.
Fixme/todo: nothing (I checked the manual) prevents user to create temp
with `#'
*/
query_buf_size
+=
table
->
s
->
table_cache_key
.
length
+
1
;
if
(
table
->
s
->
table_name
.
str
[
0
]
==
'#'
)
continue
;
else
{
found_user_tables
=
1
;
}
for
(
prev_sorted
=
NULL
,
sorted
=
thd
->
temporary_tables
;
sorted
!=
table
;
prev_sorted
=
sorted
,
sorted
=
sorted
->
next
)
{
if
(
sorted
->
s
->
table_name
.
str
[
0
]
==
'#'
||
tmpkeyval
(
thd
,
sorted
)
>
tmpkeyval
(
thd
,
table
))
{
/* move into the sorted part of the list from the unsorted */
prev_table
->
next
=
table
->
next
;
table
->
next
=
sorted
;
if
(
prev_sorted
)
{
prev_sorted
->
next
=
table
;
}
else
{
thd
->
temporary_tables
=
table
;
}
table
=
prev_table
;
break
;
}
}
}
/*
calc query_buf_size as max per sublists, one sublist per pseudo thread id.
Also stop at first occurence of `#'-named table that starts
all implicitly created temp tables
*/
for
(
max_names_len
=
0
,
table
=
thd
->
temporary_tables
;
table
&&
table
->
s
->
table_name
.
str
[
0
]
!=
'#'
;
table
=
table
->
next
)
{
uint
tmp_names_len
;
for
(
tmp_names_len
=
table
->
s
->
table_cache_key
.
length
+
1
;
table
->
next
&&
table
->
s
->
table_name
.
str
[
0
]
!=
'#'
&&
tmpkeyval
(
thd
,
table
)
==
tmpkeyval
(
thd
,
table
->
next
);
table
=
table
->
next
)
{
/*
We are going to add 4 ` around the db/table names, so 1 might not look
enough; indeed it is enough, because table->s->table_cache_key.length is
greater (by 8, because of server_id and thread_id) than db||table.
*/
tmp_names_len
+=
table
->
next
->
s
->
table_cache_key
.
length
+
1
;
}
if
(
tmp_names_len
>
max_names_len
)
max_names_len
=
tmp_names_len
;
}
if
((
query
=
alloc_root
(
thd
->
mem_root
,
query_buf_size
)))
/* allocate */
if
(
found_user_tables
&&
mysql_bin_log
.
is_open
()
&&
!
thd
->
current_stmt_binlog_row_based
&&
(
query
=
alloc_root
(
thd
->
mem_root
,
query_buf_size
+=
max_names_len
)))
// Better add "if exists", in case a RESET MASTER has been done
end
=
strmov
(
query
,
"DROP /*!40005 TEMPORARY */ TABLE IF EXISTS "
);
end
=
strmov
(
query
,
"DROP /*!40005 TEMPORARY */ TABLE IF EXISTS "
);
for
(
table
=
thd
->
temporary_tables
;
table
;
table
=
next
)
/* scan sorted tmps to generate sequence of DROP */
for
(
table
=
thd
->
temporary_tables
;
table
;
table
=
next
)
{
if
(
query
)
// we might be out of memory, but this is not fatal
if
(
query
// we might be out of memory, but this is not fatal
&&
table
->
s
->
table_name
.
str
[
0
]
!=
'#'
)
{
// skip temporary tables not created directly by the user
if
(
table
->
s
->
table_name
.
str
[
0
]
!=
'#'
)
found_user_tables
=
1
;
end
=
strxmov
(
end
,
"`"
,
table
->
s
->
db
.
str
,
"`.`"
,
table
->
s
->
table_name
.
str
,
"`,"
,
NullS
);
char
*
end_cur
;
/* Set pseudo_thread_id to be that of the processed table */
thd
->
variables
.
pseudo_thread_id
=
tmpkeyval
(
thd
,
table
);
/* Loop forward through all tables within the sublist of
common pseudo_thread_id to create single DROP query */
for
(
end_cur
=
end
;
table
&&
table
->
s
->
table_name
.
str
[
0
]
!=
'#'
&&
tmpkeyval
(
thd
,
table
)
==
thd
->
variables
.
pseudo_thread_id
;
table
=
next
)
{
end_cur
=
strxmov
(
end_cur
,
"`"
,
table
->
s
->
db
.
str
,
"`.`"
,
table
->
s
->
table_name
.
str
,
"`,"
,
NullS
);
next
=
table
->
next
;
close_temporary
(
table
,
1
,
1
);
}
thd
->
clear_error
();
/* The -1 is to remove last ',' */
Query_log_event
qinfo
(
thd
,
query
,
(
ulong
)(
end_cur
-
query
)
-
1
,
0
,
FALSE
);
/*
Imagine the thread had created a temp table, then was doing a SELECT,
and the SELECT was killed. Then it's not clever to mark the statement
above as "killed", because it's not really a statement updating data,
and there are 99.99% chances it will succeed on slave. If a real update
(one updating a persistent table) was killed on the master, then this
real update will be logged with error_code=killed, rightfully causing
the slave to stop.
*/
qinfo
.
error_code
=
0
;
mysql_bin_log
.
write
(
&
qinfo
);
}
else
{
next
=
table
->
next
;
close_temporary
(
table
,
1
,
1
);
}
next
=
table
->
next
;
close_temporary
(
table
,
1
,
1
);
}
if
(
query
&&
found_user_tables
&&
mysql_bin_log
.
is_open
()
&&
!
thd
->
current_stmt_binlog_row_based
)
// CREATE TEMP TABLE not binlogged if row-based
{
/* The -1 is to remove last ',' */
thd
->
clear_error
();
Query_log_event
qinfo
(
thd
,
query
,
(
ulong
)(
end
-
query
)
-
1
,
0
,
FALSE
);
/*
Imagine the thread had created a temp table, then was doing a SELECT, and
the SELECT was killed. Then it's not clever to mark the statement above
as "killed", because it's not really a statement updating data, and there
are 99.99% chances it will succeed on slave.
If a real update (one updating a persistent table) was killed on the
master, then this real update will be logged with error_code=killed,
rightfully causing the slave to stop.
*/
qinfo
.
error_code
=
0
;
mysql_bin_log
.
write
(
&
qinfo
);
}
thd
->
temporary_tables
=
0
;
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment