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
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
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
Show 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)
...
@@ -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
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
)
void
close_temporary_tables
(
THD
*
thd
)
{
{
TABLE
*
table
,
*
next
;
TABLE
*
next
,
char
*
query
,
*
end
;
*
prev_table
/* prev link is not maintained in TABLE's double-linked list */
,
uint
query_buf_size
;
*
table
;
bool
found_user_tables
=
0
;
char
*
query
=
(
gptr
)
0
,
*
end
;
uint
query_buf_size
,
max_names_len
;
bool
found_user_tables
;
if
(
!
thd
->
temporary_tables
)
if
(
!
thd
->
temporary_tables
)
return
;
return
;
...
@@ -1184,51 +1194,124 @@ void close_temporary_tables(THD *thd)
...
@@ -1184,51 +1194,124 @@ void close_temporary_tables(THD *thd)
LINT_INIT
(
end
);
LINT_INIT
(
end
);
query_buf_size
=
50
;
// Enough for DROP ... TABLE IF EXISTS
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
table not created directly by the user is moved to the tail.
enough; indeed it is enough, because table->table_cache_key.length is
Fixme/todo: nothing (I checked the manual) prevents user to create temp
with `#'
*/
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.
greater (by 8, because of server_id and thread_id) than db||table.
*/
*/
query_buf_size
+=
table
->
s
->
table_cache_key
.
length
+
1
;
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
// 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
char
*
end_cur
;
if
(
table
->
s
->
table_name
.
str
[
0
]
!=
'#'
)
/* Set pseudo_thread_id to be that of the processed table */
found_user_tables
=
1
;
thd
->
variables
.
pseudo_thread_id
=
tmpkeyval
(
thd
,
table
);
end
=
strxmov
(
end
,
"`"
,
table
->
s
->
db
.
str
,
"`.`"
,
/* 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
);
table
->
s
->
table_name
.
str
,
"`,"
,
NullS
);
}
next
=
table
->
next
;
next
=
table
->
next
;
close_temporary
(
table
,
1
,
1
);
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
();
thd
->
clear_error
();
Query_log_event
qinfo
(
thd
,
query
,
(
ulong
)(
end
-
query
)
-
1
,
0
,
FALSE
);
/* 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
Imagine the thread had created a temp table, then was doing a SELECT,
the SELECT was killed. Then it's not clever to mark the statement above
and the SELECT was killed. Then it's not clever to mark the statement
as "killed", because it's not really a statement updating data, and there
above as "killed", because it's not really a statement updating data,
are 99.99% chances it will succeed on slave.
and there are 99.99% chances it will succeed on slave. If a real update
If a real update (one updating a persistent table) was killed on the
(one updating a persistent table) was killed on the master, then this
master, then this real update will be logged with error_code=killed,
real update will be logged with error_code=killed, rightfully causing
rightfully causing
the slave to stop.
the slave to stop.
*/
*/
qinfo
.
error_code
=
0
;
qinfo
.
error_code
=
0
;
mysql_bin_log
.
write
(
&
qinfo
);
mysql_bin_log
.
write
(
&
qinfo
);
}
}
else
{
next
=
table
->
next
;
close_temporary
(
table
,
1
,
1
);
}
}
thd
->
temporary_tables
=
0
;
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