mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
New error messages
Test of unsigned BIGINT values Fixes for queries-per-hour Cleanup of replication code (comments and portability fixes) Make most of the binary log code 4G clean Changed syntax for GRANT ... QUERIES PER HOUR Docs/manual.texi: Fixed Changelog, upgrading to 4.0 and 4.1 TODO sections. Docs/mysqld_error.txt: Added error message. configure.in: Fix for autoconf 2.52 include/my_getopt.h: Portability fix. include/my_global.h: Portablity fix. include/mysqld_error.h: New error messages mysql-test/r/bigint.result: Test of unsigned BIGINT values. mysql-test/r/func_op.result: Test of unsigned BIGINT values. mysql-test/r/varbinary.result: Test of unsigned BIGINT values. mysql-test/t/bigint.test: Test of unsigned BIGINT values. sql/item_func.h: Optimized Item_int_func() usage. sql/lock.cc: Cleanup comments sql/log.cc: Cleanup sql/log_event.cc: Cleanup and portability fixes. sql/log_event.h: Cleanup and portability fixes. sql/mini_client.cc: Cleanup and portability fixes. sql/mysqld.cc: Fix for queries-per-hour sql/repl_failsafe.cc: Prepare for making binary log 2G clean. sql/share/czech/errmsg.txt: New error messages sql/share/danish/errmsg.txt: New error messages sql/share/dutch/errmsg.txt: New error messages sql/share/english/errmsg.txt: New error messages sql/share/estonian/errmsg.txt: New error messages sql/share/french/errmsg.txt: New error messages sql/share/german/errmsg.txt: New error messages sql/share/greek/errmsg.txt: New error messages sql/share/hungarian/errmsg.txt: New error messages sql/share/italian/errmsg.txt: New error messages sql/share/japanese/errmsg.txt: New error messages sql/share/korean/errmsg.txt: New error messages sql/share/norwegian-ny/errmsg.txt: New error messages sql/share/norwegian/errmsg.txt: New error messages sql/share/polish/errmsg.txt: New error messages sql/share/portuguese/errmsg.txt: New error messages sql/share/romanian/errmsg.txt: New error messages sql/share/russian/errmsg.txt: New error messages sql/share/slovak/errmsg.txt: New error messages sql/share/spanish/errmsg.txt: New error messages sql/share/swedish/errmsg.txt: New error messages sql/share/ukrainian/errmsg.txt: New error messages sql/slave.cc: Cleanup sql/slave.h: Cleanup sql/sql_acl.cc: Cleanup and removal of possible reserved words sql/sql_base.cc: More DBUG sql/sql_cache.cc: Cleanup & portability fixes sql/sql_class.h: Make binary log 4G clean sql/sql_delete.cc: More DBUG sql/sql_handler.cc: Cleanup & portability fixes sql/sql_parse.cc: Cleanup of queries-per-hours code sql/sql_rename.cc: Add missing DBUG_RETURN sql/sql_repl.cc: Cleanup & portability fixes sql/sql_select.cc: Cleanup & portability fixes sql/sql_show.cc: Cleanup & portability fixes sql/sql_update.cc: Small cleanup of multi-update-code (need second pass) sql/sql_yacc.yy: Changed syntax for GRANT ... QUERIES PER HOUR strings/str2int.c: Cleanup & portability fixes
This commit is contained in:
279
Docs/manual.texi
279
Docs/manual.texi
@ -2965,7 +2965,7 @@ for the records to be deleted, and then use these values to construct
|
|||||||
the @code{DELETE} statement (@code{DELETE FROM ... WHERE ... IN (key1,
|
the @code{DELETE} statement (@code{DELETE FROM ... WHERE ... IN (key1,
|
||||||
key2, ...)}).
|
key2, ...)}).
|
||||||
|
|
||||||
The second option is to use interactive SQL to contruct a set of
|
The second option is to use interactive SQL to construct a set of
|
||||||
@code{DELETE} statements automatically, using the MySQL
|
@code{DELETE} statements automatically, using the MySQL
|
||||||
extension @code{CONCAT()} (in lieu of the standard @code{||} operator).
|
extension @code{CONCAT()} (in lieu of the standard @code{||} operator).
|
||||||
For example:
|
For example:
|
||||||
@ -3686,6 +3686,7 @@ For platform-specific bugs, see the sections about compiling and porting.
|
|||||||
|
|
||||||
@menu
|
@menu
|
||||||
* TODO MySQL 4.0:: Things That Should be in Version 4.0
|
* TODO MySQL 4.0:: Things That Should be in Version 4.0
|
||||||
|
* TODO MySQL 4.1::
|
||||||
* TODO future:: Things That Must be Done in the Near Future
|
* TODO future:: Things That Must be Done in the Near Future
|
||||||
* TODO sometime:: Things That Have to be Done Sometime
|
* TODO sometime:: Things That Have to be Done Sometime
|
||||||
* TODO unplanned:: Things we don't Have any Plans to do
|
* TODO unplanned:: Things we don't Have any Plans to do
|
||||||
@ -3702,30 +3703,30 @@ standard, but with a lot of useful extensions. The challenge is to do
|
|||||||
this without sacrifying the speed or compromise the code.
|
this without sacrifying the speed or compromise the code.
|
||||||
|
|
||||||
|
|
||||||
@node TODO MySQL 4.0, TODO future, TODO, TODO
|
@node TODO MySQL 4.0, TODO MySQL 4.1, TODO, TODO
|
||||||
@subsection Things That Should be in 4.0
|
@subsection Things That Should be in 4.0
|
||||||
|
|
||||||
We have now shifted development to MySQL Server 4.0. Most of the basic
|
We have now in the final stages one the development of the MySQL Server
|
||||||
things we want to have in 4.0 are already done. The target is to quickly
|
4.0. server. The target is to quickly implement the rest of the
|
||||||
implement the rest of the following features and then shift development
|
following features and then shift development to MySQL Server
|
||||||
to MySQL Server 4.1. @xref{MySQL 4.0 In A Nutshell}.
|
4.1. @xref{MySQL 4.0 In A Nutshell}.
|
||||||
|
|
||||||
The news section for 4.0 includes a list of the features we have already
|
The news section for 4.0 includes a list of the features we have already
|
||||||
implemented in the 4.0 tree. @xref{News-4.0.x}.
|
implemented in the 4.0 tree. @xref{News-4.0.x}.
|
||||||
|
|
||||||
This section lists features not yet implemented in the current
|
This section lists features not yet implemented in the current version
|
||||||
version of MySQL Server 4.0, which will however be implemented in
|
of MySQL Server 4.0, which will however be implemented in later versions
|
||||||
later versions of MySQL 4.0. This being very volatile information,
|
of MySQL 4.0. This being very volatile information, please consider this
|
||||||
please consider this list valid only if you are reading it from
|
list valid only if you are reading it from the MySQL web site
|
||||||
the MySQL web site (@uref{http://www.mysql.com/}).
|
(@uref{http://www.mysql.com/}).
|
||||||
|
|
||||||
@itemize @bullet
|
@itemize @bullet
|
||||||
@item
|
@item
|
||||||
Allow users to change startup options without taking down the server.
|
Allow users to change startup options without taking down the server.
|
||||||
@item
|
@item
|
||||||
Fail safe replication.
|
Better command line argument handling.
|
||||||
@item
|
@item
|
||||||
New key cache
|
New key cache, which will give better performance when using many threads.
|
||||||
@item
|
@item
|
||||||
New table definition file format (@code{.frm} files) This will enable us
|
New table definition file format (@code{.frm} files) This will enable us
|
||||||
to not run out of bits when adding more table options. One will still
|
to not run out of bits when adding more table options. One will still
|
||||||
@ -3733,7 +3734,34 @@ be able to use the old @code{.frm} file format with 4.0. All newly created
|
|||||||
tables will, however, use the new format.
|
tables will, however, use the new format.
|
||||||
|
|
||||||
The new file format will enable us to add new column types, more options
|
The new file format will enable us to add new column types, more options
|
||||||
for keys and @code{FOREIGN KEY} support.
|
for keys and possible to store and retrieve @code{FOREIGN KEY} definitions.
|
||||||
|
@item
|
||||||
|
@code{SHOW COLUMNS FROM table_name} (used by @code{mysql} client to allow
|
||||||
|
expansions of column names) should not open the table, but only the
|
||||||
|
definition file. This will require less memory and be much faster.
|
||||||
|
@item
|
||||||
|
@code{SET SQL_DEFAULT_TABLE_TYPE=[MyISAM | INNODB | BDB | HEAP]}.
|
||||||
|
@end itemize
|
||||||
|
|
||||||
|
|
||||||
|
@node TODO MySQL 4.1, TODO future, TODO MySQL 4.0, TODO
|
||||||
|
@subsection Things That Should be in 4.1
|
||||||
|
|
||||||
|
We will start working on MySQL 4.1 as soon as MySQL 4.0 goes into beta.
|
||||||
|
|
||||||
|
The following features is the ones we plan that should be in MySQL 4.1.
|
||||||
|
Note that because we have many developers that are working on different
|
||||||
|
projects, there will also be many additional features. There is also a
|
||||||
|
small change that some of these features will be added to MySQL 4.0.
|
||||||
|
|
||||||
|
@itemize @bullet
|
||||||
|
@item
|
||||||
|
Subqueries.
|
||||||
|
@code{SELECT id FROM t WHERE grp IN (SELECT grp FROM g WHERE u > 100)}
|
||||||
|
@item
|
||||||
|
Foreign keys, including cascading delete.
|
||||||
|
@item
|
||||||
|
Fail safe replication.
|
||||||
@item
|
@item
|
||||||
Replication should work with @code{RAND()} and user variables @code{@@var}.
|
Replication should work with @code{RAND()} and user variables @code{@@var}.
|
||||||
@item
|
@item
|
||||||
@ -3741,18 +3769,21 @@ Online backup with very low performance penalty. The online backup will
|
|||||||
make it easy to add a new replication slave without taking down the
|
make it easy to add a new replication slave without taking down the
|
||||||
master.
|
master.
|
||||||
@item
|
@item
|
||||||
|
Derived tables.
|
||||||
|
@example
|
||||||
|
SELECT a.col1, b.col2
|
||||||
|
FROM (SELECT MAX(col1) AS col1 FROM root_table) a,
|
||||||
|
other_table b
|
||||||
|
WHERE a.col1=b.col1;
|
||||||
|
@end example
|
||||||
|
|
||||||
|
This could be done by automatically creating temporary tables for the
|
||||||
|
derived tables for the duration of the query.
|
||||||
|
@item
|
||||||
Allow @code{DELETE} on @code{MyISAM} tables to use the record cache.
|
Allow @code{DELETE} on @code{MyISAM} tables to use the record cache.
|
||||||
To do this, we need to update the threads record cache when we update
|
To do this, we need to update the threads record cache when we update
|
||||||
the @code{.MYD} file.
|
the @code{.MYD} file.
|
||||||
@item
|
@item
|
||||||
Character set casts and syntax for handling multiple character sets.
|
|
||||||
@item
|
|
||||||
Help for all commands from the client.
|
|
||||||
@item
|
|
||||||
@code{SHOW COLUMNS FROM table_name} (used by @code{mysql} client to allow
|
|
||||||
expansions of column names) should not open the table, but only the
|
|
||||||
definition file. This will require less memory and be much faster.
|
|
||||||
@item
|
|
||||||
When using @code{SET CHARACTER SET} we should translate the whole query
|
When using @code{SET CHARACTER SET} we should translate the whole query
|
||||||
at once and not only strings. This will enable users to use the translated
|
at once and not only strings. This will enable users to use the translated
|
||||||
characters in database, table and column names.
|
characters in database, table and column names.
|
||||||
@ -3765,46 +3796,30 @@ of @code{analyze} is run on all sub tables.
|
|||||||
@code{RENAME TABLE} on a table used in an active @code{MERGE} table may
|
@code{RENAME TABLE} on a table used in an active @code{MERGE} table may
|
||||||
corrupt the table.
|
corrupt the table.
|
||||||
@item
|
@item
|
||||||
@code{SET SQL_DEFAULT_TABLE_TYPE=[MyISAM | INNODB | BDB | HEAP]}.
|
A faster, smaller embedded MySQL library. (Compatible with the old one)
|
||||||
@end itemize
|
|
||||||
|
|
||||||
|
|
||||||
@node TODO future, TODO sometime, TODO MySQL 4.0, TODO
|
|
||||||
@subsection Things That Must be Done in the Real Near Future
|
|
||||||
|
|
||||||
@itemize @bullet
|
|
||||||
@item
|
@item
|
||||||
Subqueries.
|
Stable openssl support. (MySQL 4.0 supports rudimentary, not 100 % tested
|
||||||
@code{SELECT id FROM t WHERE grp IN (SELECT grp FROM g WHERE u > 100)}
|
support for openssl).
|
||||||
@item
|
@item
|
||||||
Atomic multi-table updates, eg @code{update items,month set
|
Add support for sorting on @code{UNICODE}.
|
||||||
items.price=month.price where items.id=month.id;};
|
|
||||||
@item
|
@item
|
||||||
Derived tables.
|
Character set casts and syntax for handling multiple character sets.
|
||||||
@example
|
|
||||||
SELECT a.col1, b.col2
|
|
||||||
FROM (SELECT MAX(col1) AS col1 FROM root_table) a,
|
|
||||||
other_table b
|
|
||||||
WHERE a.col1=b.col1;
|
|
||||||
@end example
|
|
||||||
|
|
||||||
This could be done by automatically creating temporary tables for the
|
|
||||||
derived tables for the duration of the query.
|
|
||||||
@item
|
@item
|
||||||
Add @code{PREPARE} of statements and sending of parameters to @code{mysqld}.
|
When using @code{SET CHARACTER SET} we should translate the whole query
|
||||||
|
at once and not only strings. This will enable users to use the translated
|
||||||
|
characters in database, table and column names.
|
||||||
@item
|
@item
|
||||||
Extend the client/server protocol to support warnings.
|
Help for all commands from the client.
|
||||||
@item
|
@item
|
||||||
Add options to the client/server protocol to get progress notes
|
New faster client/server protocol which will support prepared statements,
|
||||||
for long running commands.
|
bound parameters and bound result columns, binary transfer of data,
|
||||||
|
warnings...
|
||||||
@item
|
@item
|
||||||
Add database and real table name (in case of alias) to the MYSQL_FIELD
|
Add database and real table name (in case of alias) to the MYSQL_FIELD
|
||||||
structure.
|
structure.
|
||||||
@item
|
@item
|
||||||
Don't allow more than a defined number of threads to run MyISAM recover
|
Add options to the client/server protocol to get progress notes
|
||||||
at the same time.
|
for long running commands.
|
||||||
@item
|
|
||||||
Change @code{INSERT ... SELECT} to optionally use concurrent inserts.
|
|
||||||
@item
|
@item
|
||||||
Implement @code{RENAME DATABASE}. To make this safe for all table handlers,
|
Implement @code{RENAME DATABASE}. To make this safe for all table handlers,
|
||||||
it should work as follows:
|
it should work as follows:
|
||||||
@ -3818,16 +3833,45 @@ we do with the @code{RENAME} command.
|
|||||||
Drop the old database.
|
Drop the old database.
|
||||||
@end itemize
|
@end itemize
|
||||||
@item
|
@item
|
||||||
|
Add true @code{VARCHAR} support (There is already support for this in
|
||||||
|
@code{MyISAM}).
|
||||||
|
@item
|
||||||
|
Optimise @code{BIT} type to take 1 bit (now @code{BIT} takes 1 char).
|
||||||
|
@item
|
||||||
|
New internal file interface change. This will make all file handling much
|
||||||
|
more general and make it easier to add extensions like RAID nicely.
|
||||||
|
(The current implementation is a hack).
|
||||||
|
@item
|
||||||
|
Better in-memory (@code{HEAP}) tables:
|
||||||
|
@itemize @bullet
|
||||||
|
@item
|
||||||
|
Support for B-tree indexes
|
||||||
|
@item
|
||||||
|
Dynamic size rows
|
||||||
|
@item
|
||||||
|
Faster row handling (less copying)
|
||||||
|
@end itemize
|
||||||
|
@end itemize
|
||||||
|
|
||||||
|
|
||||||
|
@node TODO future, TODO sometime, TODO MySQL 4.1, TODO
|
||||||
|
@subsection Things That Must be Done in the Real Near Future
|
||||||
|
|
||||||
|
@itemize @bullet
|
||||||
|
@item
|
||||||
|
Atomic multi-table updates, eg @code{update items,month set
|
||||||
|
items.price=month.price where items.id=month.id;};
|
||||||
|
@item
|
||||||
|
Don't allow more than a defined number of threads to run MyISAM recover
|
||||||
|
at the same time.
|
||||||
|
@item
|
||||||
|
Change @code{INSERT ... SELECT} to optionally use concurrent inserts.
|
||||||
|
@item
|
||||||
Return the original field types() when doing @code{SELECT MIN(column)
|
Return the original field types() when doing @code{SELECT MIN(column)
|
||||||
... GROUP BY}.
|
... GROUP BY}.
|
||||||
@item
|
@item
|
||||||
Multiple result sets.
|
Multiple result sets.
|
||||||
@item
|
@item
|
||||||
Change the protocol to allow binary transfer of values. To do this
|
|
||||||
efficiently, we need to add an API to allow binding of variables.
|
|
||||||
@item
|
|
||||||
Add @code{PREPARE} of statements and sending of parameters to @code{mysqld}.
|
|
||||||
@item
|
|
||||||
Make it possible to specify @code{long_query_time} with a granularity
|
Make it possible to specify @code{long_query_time} with a granularity
|
||||||
in microseconds.
|
in microseconds.
|
||||||
@item
|
@item
|
||||||
@ -3836,6 +3880,8 @@ options like database in use, time and date...
|
|||||||
@item
|
@item
|
||||||
Link the @code{myisampack} code into the server.
|
Link the @code{myisampack} code into the server.
|
||||||
@item
|
@item
|
||||||
|
Port of the MySQL code to QNX.
|
||||||
|
@item
|
||||||
Port of the MySQL code to BeOS.
|
Port of the MySQL code to BeOS.
|
||||||
@item
|
@item
|
||||||
Port of the MySQL clients to LynxOS.
|
Port of the MySQL clients to LynxOS.
|
||||||
@ -3864,10 +3910,6 @@ Allow join on key parts (optimisation issue).
|
|||||||
@code{INSERT SQL_CONCURRENT} and @code{mysqld --concurrent-insert} to do
|
@code{INSERT SQL_CONCURRENT} and @code{mysqld --concurrent-insert} to do
|
||||||
a concurrent insert at the end of the file if the file is read-locked.
|
a concurrent insert at the end of the file if the file is read-locked.
|
||||||
@item
|
@item
|
||||||
Remember @code{FOREIGN} key definitions in the @file{.frm} file.
|
|
||||||
@item
|
|
||||||
Cascading @code{DELETE}
|
|
||||||
@item
|
|
||||||
Server side cursors.
|
Server side cursors.
|
||||||
@item
|
@item
|
||||||
Check if @code{lockd} works with modern Linux kernels; If not, we have
|
Check if @code{lockd} works with modern Linux kernels; If not, we have
|
||||||
@ -3891,8 +3933,6 @@ an @code{INSERT} that doesn't contain a column that doesn't have a
|
|||||||
Fix @file{libmysql.c} to allow two @code{mysql_query()} commands in a row
|
Fix @file{libmysql.c} to allow two @code{mysql_query()} commands in a row
|
||||||
without reading results or give a nice error message when one does this.
|
without reading results or give a nice error message when one does this.
|
||||||
@item
|
@item
|
||||||
Optimise @code{BIT} type to take 1 bit (now @code{BIT} takes 1 char).
|
|
||||||
@item
|
|
||||||
Check why MIT-pthreads @code{ctime()} doesn't work on some FreeBSD systems.
|
Check why MIT-pthreads @code{ctime()} doesn't work on some FreeBSD systems.
|
||||||
@item
|
@item
|
||||||
Add an @code{IMAGE} option to @code{LOAD DATA INFILE} to not update
|
Add an @code{IMAGE} option to @code{LOAD DATA INFILE} to not update
|
||||||
@ -3933,15 +3973,10 @@ and maybe
|
|||||||
data_line - the line from the data file
|
data_line - the line from the data file
|
||||||
@end example
|
@end example
|
||||||
@item
|
@item
|
||||||
Add true @code{VARCHAR} support (There is already support for this in
|
|
||||||
@code{MyISAM}).
|
|
||||||
@item
|
|
||||||
Automatic output from @code{mysql} to Netscape.
|
Automatic output from @code{mysql} to Netscape.
|
||||||
@item
|
@item
|
||||||
@code{LOCK DATABASES}. (with various options)
|
@code{LOCK DATABASES}. (with various options)
|
||||||
@item
|
@item
|
||||||
Change sort to allocate memory in ``hunks'' to get better memory utilisation.
|
|
||||||
@item
|
|
||||||
@code{DECIMAL} and @code{NUMERIC} types can't read exponential numbers;
|
@code{DECIMAL} and @code{NUMERIC} types can't read exponential numbers;
|
||||||
@code{Field_decimal::store(const char *from,uint len)} must be recoded
|
@code{Field_decimal::store(const char *from,uint len)} must be recoded
|
||||||
to fix this.
|
to fix this.
|
||||||
@ -3965,8 +4000,6 @@ table. This would be a bit slow if you requested information about all tables,
|
|||||||
but very flexible. @code{SHOW INFO FROM tbl_name} for basic table information
|
but very flexible. @code{SHOW INFO FROM tbl_name} for basic table information
|
||||||
should be implemented.
|
should be implemented.
|
||||||
@item
|
@item
|
||||||
Add support for UNICODE.
|
|
||||||
@item
|
|
||||||
@code{NATURAL JOIN}.
|
@code{NATURAL JOIN}.
|
||||||
@item
|
@item
|
||||||
Allow @code{select a from crash_me left join crash_me2 using (a)}; In this
|
Allow @code{select a from crash_me left join crash_me2 using (a)}; In this
|
||||||
@ -4006,9 +4039,6 @@ Change that @code{ALTER TABLE} doesn't abort clients that executes
|
|||||||
Fix that when columns referenced in an @code{UPDATE} clause contains the old
|
Fix that when columns referenced in an @code{UPDATE} clause contains the old
|
||||||
values before the update started.
|
values before the update started.
|
||||||
@item
|
@item
|
||||||
@code{myisamchk}, @code{REPAIR} and @code{OPTIMIZE TABLE} should be able
|
|
||||||
to handle cases where the data and/or index files are symbolic links.
|
|
||||||
@item
|
|
||||||
Add simulation of @code{pread()}/@code{pwrite()} on Windows to enable
|
Add simulation of @code{pread()}/@code{pwrite()} on Windows to enable
|
||||||
concurrent inserts.
|
concurrent inserts.
|
||||||
@item
|
@item
|
||||||
@ -6436,7 +6466,7 @@ sometimes required. If you have problems, we recommend trying GNU
|
|||||||
If you are using a recent version of @strong{gcc}, recent enough to understand
|
If you are using a recent version of @strong{gcc}, recent enough to understand
|
||||||
@code{-fno-exceptions} option, it is @strong{very important} that you use
|
@code{-fno-exceptions} option, it is @strong{very important} that you use
|
||||||
it. Otherwise, you may compile a binary that crashes randomly. We also
|
it. Otherwise, you may compile a binary that crashes randomly. We also
|
||||||
recommend that you use @code{-felide-contructors} and @code{-fno-rtti} along
|
recommend that you use @code{-felide-constructors} and @code{-fno-rtti} along
|
||||||
with @code{-fno-exceptions}. When in doubt, do the following:
|
with @code{-fno-exceptions}. When in doubt, do the following:
|
||||||
|
|
||||||
@example
|
@example
|
||||||
@ -6969,8 +6999,9 @@ speed of your connection; be patient.
|
|||||||
@item
|
@item
|
||||||
You will need GNU @code{autoconf 2.13}, @code{automake 1.4},
|
You will need GNU @code{autoconf 2.13}, @code{automake 1.4},
|
||||||
@code{libtool}, and @code{m4} to run the next set of commands.
|
@code{libtool}, and @code{m4} to run the next set of commands.
|
||||||
Note that the new versions of @code{autoconf} (2.52) and @code{automake}
|
|
||||||
(1.5) do not work.
|
If you are using the 3.23 tree the new versions of @code{autoconf}
|
||||||
|
(2.52) and @code{automake} (1.5) will not work.
|
||||||
|
|
||||||
If you get some strange error during this stage, check that you really
|
If you get some strange error during this stage, check that you really
|
||||||
have @code{libtool} installed!
|
have @code{libtool} installed!
|
||||||
@ -8100,12 +8131,24 @@ than it had in 3.23.
|
|||||||
@item
|
@item
|
||||||
@code{SIGNED} is a reserved word.
|
@code{SIGNED} is a reserved word.
|
||||||
@item
|
@item
|
||||||
|
The result of all bitwise operators @code{|}, @code{&}, @code{<<},
|
||||||
|
@code{>>} and @code{~} is now unsigned. This may cause problems if your
|
||||||
|
are using them in a context where you want an signed result. @xref{Cast
|
||||||
|
Functions}.
|
||||||
|
@item
|
||||||
|
@strong{NOTE:} When you use subtraction between integers values where
|
||||||
|
one is of type @code{UNSIGNED}, the result will be unsigned! In other
|
||||||
|
words, before upgrading to MySQL 4.0, you should check your application
|
||||||
|
for cases where you are subtracting a value from an unsigned entity
|
||||||
|
and want a negative answer or subtracting an unsigned value from a an
|
||||||
|
integer column. @xref{Cast Functions}.
|
||||||
|
@item
|
||||||
To use @code{MATCH ... AGAINST (... IN BOOLEAN MODE)} with your tables,
|
To use @code{MATCH ... AGAINST (... IN BOOLEAN MODE)} with your tables,
|
||||||
you need to rebuild them with @code{ALTER TABLE table_name TYPE=MyISAM},
|
you need to rebuild them with @code{ALTER TABLE table_name TYPE=MyISAM},
|
||||||
@strong{even} if they are of @code{MyISAM} type.
|
@strong{even} if they are of @code{MyISAM} type.
|
||||||
@item
|
@item
|
||||||
@code{LOCATE()} and @code{INSTR()} are case sensitive if neither
|
@code{LOCATE()} and @code{INSTR()} are case sensitive if one of the
|
||||||
argument is a binary string.
|
arguments is a binary string.
|
||||||
@item
|
@item
|
||||||
@code{HEX(string)} now returns the characters in string converted to
|
@code{HEX(string)} now returns the characters in string converted to
|
||||||
hexadecimal. If you want to convert a number to hexadecimal, you should
|
hexadecimal. If you want to convert a number to hexadecimal, you should
|
||||||
@ -16159,7 +16202,7 @@ GRANT priv_type [(column_list)] [, priv_type [(column_list)] ...]
|
|||||||
[CIPHER cipher [AND]]
|
[CIPHER cipher [AND]]
|
||||||
[ISSUER issuer [AND]]
|
[ISSUER issuer [AND]]
|
||||||
[SUBJECT subject]]
|
[SUBJECT subject]]
|
||||||
[WITH GRANT OPTION]
|
[WITH [GRANT OPTION | MAX_QUERIES_PER_HOUR=#]]
|
||||||
|
|
||||||
REVOKE priv_type [(column_list)] [, priv_type [(column_list)] ...]
|
REVOKE priv_type [(column_list)] [, priv_type [(column_list)] ...]
|
||||||
ON @{tbl_name | * | *.* | db_name.*@}
|
ON @{tbl_name | * | *.* | db_name.*@}
|
||||||
@ -16320,6 +16363,12 @@ to other users any privileges the user has at the specified privilege level.
|
|||||||
You should be careful to whom you give the @strong{grant} privilege, as two
|
You should be careful to whom you give the @strong{grant} privilege, as two
|
||||||
users with different privileges may be able to join privileges!
|
users with different privileges may be able to join privileges!
|
||||||
|
|
||||||
|
@code{MAX_QUERIES_PER_HOUR=#} limits the number of queries the user can
|
||||||
|
do during one hour. If @code{#} is 0, then this means that there is no
|
||||||
|
limit of the number of queries. This works by MySQL resetting a user
|
||||||
|
specific query counter to 0, after it has gone more than one hour
|
||||||
|
since the counter started incrementing.
|
||||||
|
|
||||||
You cannot grant another user a privilege you don't have yourself;
|
You cannot grant another user a privilege you don't have yourself;
|
||||||
the @strong{grant} privilege allows you to give away only those privileges
|
the @strong{grant} privilege allows you to give away only those privileges
|
||||||
you possess.
|
you possess.
|
||||||
@ -28068,6 +28117,10 @@ that are optional.
|
|||||||
Note that if you specify @code{ZEROFILL} for a column, MySQL will
|
Note that if you specify @code{ZEROFILL} for a column, MySQL will
|
||||||
automatically add the @code{UNSIGNED} attribute to the column.
|
automatically add the @code{UNSIGNED} attribute to the column.
|
||||||
|
|
||||||
|
@strong{Warning:} You should be aware that when you use subtraction
|
||||||
|
between integers values where one is of type @code{UNSIGNED}, the result
|
||||||
|
will be unsigned! @xref{Cast Functions}.
|
||||||
|
|
||||||
@table @code
|
@table @code
|
||||||
@tindex TINYINT
|
@tindex TINYINT
|
||||||
@item TINYINT[(M)] [UNSIGNED] [ZEROFILL]
|
@item TINYINT[(M)] [UNSIGNED] [ZEROFILL]
|
||||||
@ -30841,9 +30894,13 @@ make string comparison even more flexible.
|
|||||||
@node Arithmetic functions, Mathematical functions, Numeric Functions, Numeric Functions
|
@node Arithmetic functions, Mathematical functions, Numeric Functions, Numeric Functions
|
||||||
@subsubsection Arithmetic Operations
|
@subsubsection Arithmetic Operations
|
||||||
|
|
||||||
|
@cindex operators, cast
|
||||||
The usual arithmetic operators are available. Note that in the case of
|
The usual arithmetic operators are available. Note that in the case of
|
||||||
@samp{-}, @samp{+}, and @samp{*}, the result is calculated with
|
@samp{-}, @samp{+}, and @samp{*}, the result is calculated with
|
||||||
@code{BIGINT} (64-bit) precision if both arguments are integers!
|
@code{BIGINT} (64-bit) precision if both arguments are integers!
|
||||||
|
If one of the argument is an unsigned integer, and the other argument
|
||||||
|
is also an integer, the result will be an unsigned integer.
|
||||||
|
@xref{Cast Functions}.
|
||||||
|
|
||||||
@cindex operations, arithmetic
|
@cindex operations, arithmetic
|
||||||
@cindex arithmetic expressions
|
@cindex arithmetic expressions
|
||||||
@ -30879,8 +30936,9 @@ mysql> select 18014398509481984*18014398509481984;
|
|||||||
-> 0
|
-> 0
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
The result of the last expression is incorrect because the result of the integer
|
The result of the last expression is incorrect because the result of the
|
||||||
multiplication exceeds the 64-bit range of @code{BIGINT} calculations.
|
integer multiplication exceeds the 64-bit range of @code{BIGINT}
|
||||||
|
calculations.
|
||||||
|
|
||||||
@findex / (division)
|
@findex / (division)
|
||||||
@findex division (/)
|
@findex division (/)
|
||||||
@ -31903,10 +31961,10 @@ mysql> select 1+'1';
|
|||||||
|
|
||||||
MySQL supports arithmetic with both signed and unsigned 64 bit values.
|
MySQL supports arithmetic with both signed and unsigned 64 bit values.
|
||||||
If you are using an numerical operations (like @code{+}) and one of the
|
If you are using an numerical operations (like @code{+}) and one of the
|
||||||
operands are @code{unsigned}, then the result will be unsigned. You can
|
operands are @code{unsigned integer}, then the result will be unsigned.
|
||||||
override this by using the @code{SIGNED} and @code{UNSIGNED} cast
|
You can override this by using the @code{SIGNED} and @code{UNSIGNED}
|
||||||
operators, which will cast the operation to signed respective unsigned
|
cast operators, which will cast the operation to signed respective
|
||||||
64 bit integer.
|
unsigned 64 bit integer.
|
||||||
|
|
||||||
@example
|
@example
|
||||||
mysql> select CAST(1-2 AS UNSIGNED)
|
mysql> select CAST(1-2 AS UNSIGNED)
|
||||||
@ -31915,8 +31973,33 @@ mysql select CAST(CAST(1-2 AS UNSIGNED) AS SIGNED);
|
|||||||
-> -1
|
-> -1
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
|
Note that if either operation is a floating point value (In this context
|
||||||
|
@code{DECIMAL()} is regarded as a floating point value) the result will
|
||||||
|
be a floating point value and is not affected by the above rule.
|
||||||
|
|
||||||
|
@example
|
||||||
|
mysql> select CAST(1 AS UNSIGNED) -2.0
|
||||||
|
-> -1.0
|
||||||
|
@end example
|
||||||
|
|
||||||
|
If you are using a string in an arithmetic operation, this is converted
|
||||||
|
to a floating point number.
|
||||||
|
|
||||||
The @code{CAST()} and @code{CONVERT()} function was added in MySQL 4.0.2.
|
The @code{CAST()} and @code{CONVERT()} function was added in MySQL 4.0.2.
|
||||||
|
|
||||||
|
The handing of unsigned values was changed in MySQL 4.0 to be able to
|
||||||
|
support @code{BIGINT} values properly. If you have some code that you
|
||||||
|
want to run in both MySQL 4.0 and 3.23 (in which case you probably can't
|
||||||
|
use the CAST function), you can use the following trick to get a signed
|
||||||
|
result when subtracting two unsigned integer columns:
|
||||||
|
|
||||||
|
@example
|
||||||
|
SELECT (unsigned_column_1+0.0)-(unsigned_column_2+0.0);
|
||||||
|
@end example
|
||||||
|
|
||||||
|
The idea is that the columns are converted to floating point before doing
|
||||||
|
the subtraction.
|
||||||
|
|
||||||
@node Other Functions, Group by functions, Cast Functions, Functions
|
@node Other Functions, Group by functions, Cast Functions, Functions
|
||||||
@subsection Other Functions
|
@subsection Other Functions
|
||||||
|
|
||||||
@ -31941,12 +32024,14 @@ these operators have a maximum range of 64 bits.
|
|||||||
@findex | (bitwise OR)
|
@findex | (bitwise OR)
|
||||||
@findex OR, bitwise
|
@findex OR, bitwise
|
||||||
@item |
|
@item |
|
||||||
Bitwise OR:
|
Bitwise OR
|
||||||
@example
|
@example
|
||||||
mysql> select 29 | 15;
|
mysql> select 29 | 15;
|
||||||
-> 31
|
-> 31
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
|
The result is an unsigned 64 bit integer.
|
||||||
|
|
||||||
@findex & (bitwise AND)
|
@findex & (bitwise AND)
|
||||||
@findex AND, bitwise
|
@findex AND, bitwise
|
||||||
@item &
|
@item &
|
||||||
@ -31956,6 +32041,8 @@ mysql> select 29 & 15;
|
|||||||
-> 13
|
-> 13
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
|
The result is an unsigned 64 bit integer.
|
||||||
|
|
||||||
@findex << (left shift)
|
@findex << (left shift)
|
||||||
@item <<
|
@item <<
|
||||||
Shifts a longlong (@code{BIGINT}) number to the left:
|
Shifts a longlong (@code{BIGINT}) number to the left:
|
||||||
@ -31964,6 +32051,8 @@ mysql> select 1 << 2;
|
|||||||
-> 4
|
-> 4
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
|
The result is an unsigned 64 bit integer.
|
||||||
|
|
||||||
@findex >> (right shift)
|
@findex >> (right shift)
|
||||||
@item >>
|
@item >>
|
||||||
Shifts a longlong (@code{BIGINT}) number to the right:
|
Shifts a longlong (@code{BIGINT}) number to the right:
|
||||||
@ -31972,6 +32061,8 @@ mysql> select 4 >> 2;
|
|||||||
-> 1
|
-> 1
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
|
The result is an unsigned 64 bit integer.
|
||||||
|
|
||||||
@findex ~
|
@findex ~
|
||||||
@item ~
|
@item ~
|
||||||
Invert all bits:
|
Invert all bits:
|
||||||
@ -31980,6 +32071,8 @@ mysql> select 5 & ~1;
|
|||||||
-> 4
|
-> 4
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
|
The result is an unsigned 64 bit integer.
|
||||||
|
|
||||||
@findex BIT_COUNT()
|
@findex BIT_COUNT()
|
||||||
@item BIT_COUNT(N)
|
@item BIT_COUNT(N)
|
||||||
Returns the number of bits that are set in the argument @code{N}:
|
Returns the number of bits that are set in the argument @code{N}:
|
||||||
@ -35091,6 +35184,7 @@ If MySQL encounters any errors in a multiple table rename, it
|
|||||||
will do a reverse rename for all renamed tables to get everything back
|
will do a reverse rename for all renamed tables to get everything back
|
||||||
to the original state.
|
to the original state.
|
||||||
|
|
||||||
|
@code{RENAME TABLE} was added in MySQL 3.23.23.
|
||||||
|
|
||||||
@node DROP TABLE, CREATE INDEX, RENAME TABLE, Data Definition
|
@node DROP TABLE, CREATE INDEX, RENAME TABLE, Data Definition
|
||||||
@subsection @code{DROP TABLE} Syntax
|
@subsection @code{DROP TABLE} Syntax
|
||||||
@ -48267,6 +48361,11 @@ Our TODO section contains what we plan to have in 4.0. @xref{TODO MySQL 4.0}.
|
|||||||
|
|
||||||
@itemize @bullet
|
@itemize @bullet
|
||||||
@item
|
@item
|
||||||
|
Added @code{WITH MAX_QUERIES_PER_HOUR=#} to @code{GRANT} command.
|
||||||
|
@item
|
||||||
|
The type returned for all bit functions (@code{|}, @code{<<} ...) are now of
|
||||||
|
type @code{unsigned integer}.
|
||||||
|
@item
|
||||||
Added detection if @code{nan} values in MyISAM to make it possible to
|
Added detection if @code{nan} values in MyISAM to make it possible to
|
||||||
repair tables with @code{nan} in float or double columns.
|
repair tables with @code{nan} in float or double columns.
|
||||||
@item
|
@item
|
||||||
@ -48377,8 +48476,8 @@ able to use boolean fulltext search}.
|
|||||||
@code{LOCATE()} and @code{INSTR()} are case sensitive if neither
|
@code{LOCATE()} and @code{INSTR()} are case sensitive if neither
|
||||||
argument is a binary string.
|
argument is a binary string.
|
||||||
@item
|
@item
|
||||||
Changed @code{RND()} initialization so that @code{RND(N)} and @code{RND(N+1)}
|
Changed @code{RAND()} initialization so that @code{RAND(N)} and
|
||||||
are more distinct.
|
@code{RAND(N+1)} are more distinct.
|
||||||
@item
|
@item
|
||||||
Fixed core dump bug in @code{UPDATE ... ORDER BY}.
|
Fixed core dump bug in @code{UPDATE ... ORDER BY}.
|
||||||
@item
|
@item
|
||||||
@ -48603,7 +48702,7 @@ not yet 100% confident in this code.
|
|||||||
@appendixsubsec Changes in release 3.23.47
|
@appendixsubsec Changes in release 3.23.47
|
||||||
@itemize @bullet
|
@itemize @bullet
|
||||||
@item
|
@item
|
||||||
Fixed in when using the following construct:
|
Fixed bug when using the following construct:
|
||||||
@code{SELECT ... WHERE key=@@var_name OR $key=@@var_name2}
|
@code{SELECT ... WHERE key=@@var_name OR $key=@@var_name2}
|
||||||
@item
|
@item
|
||||||
Restrict InnoDB keys to 500 bytes.
|
Restrict InnoDB keys to 500 bytes.
|
||||||
@ -50031,7 +50130,7 @@ that both non-threaded (@code{-lmysqlclient}) and threaded
|
|||||||
against a threaded @code{-lmysqlclient} will need to link against
|
against a threaded @code{-lmysqlclient} will need to link against
|
||||||
@code{libmysqlclient_r} now.
|
@code{libmysqlclient_r} now.
|
||||||
@item
|
@item
|
||||||
Added atomic @code{RENAME} command.
|
Added atomic @code{RENAME TABLE} command.
|
||||||
@item
|
@item
|
||||||
Don't count entries with @code{NULL} in @code{COUNT(DISTINCT ...)}.
|
Don't count entries with @code{NULL} in @code{COUNT(DISTINCT ...)}.
|
||||||
@item
|
@item
|
||||||
|
140
Docs/my_sys.txt
Normal file
140
Docs/my_sys.txt
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
Functions i mysys: (For flags se my_sys.h)
|
||||||
|
|
||||||
|
int my_copy _A((const char *from,const char *to,myf MyFlags));
|
||||||
|
- Copy file
|
||||||
|
|
||||||
|
int my_delete _A((const char *name,myf MyFlags));
|
||||||
|
- Delete file
|
||||||
|
|
||||||
|
int my_getwd _A((string buf,uint size,myf MyFlags));
|
||||||
|
int my_setwd _A((const char *dir,myf MyFlags));
|
||||||
|
- Get and set working directory
|
||||||
|
|
||||||
|
string my_tempnam _A((const char *pfx,myf MyFlags));
|
||||||
|
- Make a uniq temp file name by using dir and adding something after
|
||||||
|
pfx to make name uniq. Name is made by adding a uniq 6 length-string
|
||||||
|
and TMP_EXT after pfx.
|
||||||
|
Returns pointer to malloced area for filename. Should be freed by
|
||||||
|
free().
|
||||||
|
|
||||||
|
File my_open _A((const char *FileName,int Flags,myf MyFlags));
|
||||||
|
File my_create _A((const char *FileName,int CreateFlags,
|
||||||
|
int AccsesFlags, myf MyFlags));
|
||||||
|
int my_close _A((File Filedes,myf MyFlags));
|
||||||
|
uint my_read _A((File Filedes,byte *Buffer,uint Count,myf MyFlags));
|
||||||
|
uint my_write _A((File Filedes,const byte *Buffer,uint Count,
|
||||||
|
myf MyFlags));
|
||||||
|
ulong my_seek _A((File fd,ulong pos,int whence,myf MyFlags));
|
||||||
|
ulong my_tell _A((File fd,myf MyFlags));
|
||||||
|
- Use instead of open,open-with-create-flag, close read and write
|
||||||
|
to get automatic error-messages (flag: MYF_WME) and only have
|
||||||
|
to test for != 0 if error (flag: MY_NABP).
|
||||||
|
|
||||||
|
int my_rename _A((const char *from,const char *to,myf MyFlags));
|
||||||
|
- Rename file
|
||||||
|
|
||||||
|
FILE *my_fopen _A((const char *FileName,int Flags,myf MyFlags));
|
||||||
|
FILE *my_fdopen _A((File Filedes,int Flags,myf MyFlags));
|
||||||
|
int my_fclose _A((FILE *fd,myf MyFlags));
|
||||||
|
uint my_fread _A((FILE *stream,byte *Buffer,uint Count,myf MyFlags));
|
||||||
|
uint my_fwrite _A((FILE *stream,const byte *Buffer,uint Count,
|
||||||
|
myf MyFlags));
|
||||||
|
ulong my_fseek _A((FILE *stream,ulong pos,int whence,myf MyFlags));
|
||||||
|
ulong my_ftell _A((FILE *stream,myf MyFlags));
|
||||||
|
- Same read-interface for streams as for files
|
||||||
|
|
||||||
|
gptr _mymalloc _A((uint uSize,const char *sFile,
|
||||||
|
uint uLine, myf MyFlag));
|
||||||
|
gptr _myrealloc _A((string pPtr,uint uSize,const char *sFile,
|
||||||
|
uint uLine, myf MyFlag));
|
||||||
|
void _myfree _A((gptr pPtr,const char *sFile,uint uLine));
|
||||||
|
int _sanity _A((const char *sFile,unsigned int uLine));
|
||||||
|
gptr _myget_copy_of_memory _A((const byte *from,uint length,
|
||||||
|
const char *sFile, uint uLine,
|
||||||
|
myf MyFlag));
|
||||||
|
- malloc(size,myflag) is mapped to this functions if not compiled
|
||||||
|
with -DSAFEMALLOC
|
||||||
|
|
||||||
|
void TERMINATE _A((void));
|
||||||
|
- Writes malloc-info on stdout if compiled with -DSAFEMALLOC.
|
||||||
|
|
||||||
|
int my_chsize _A((File fd,ulong newlength,myf MyFlags));
|
||||||
|
- Change size of file
|
||||||
|
|
||||||
|
void my_error _D((int nr,myf MyFlags, ...));
|
||||||
|
- Writes message using error number (se mysys/errors.h) on
|
||||||
|
stdout or curses if MYSYS_PROGRAM_USES_CURSES() is called.
|
||||||
|
|
||||||
|
void my_message _A((const char *str,myf MyFlags));
|
||||||
|
- Writes message-string on
|
||||||
|
stdout or curses if MYSYS_PROGRAM_USES_CURSES() is called.
|
||||||
|
|
||||||
|
void my_init _A((void ));
|
||||||
|
- Start each program (in main) with this.
|
||||||
|
void my_end _A((int infoflag));
|
||||||
|
- Gives info about program.
|
||||||
|
- If infoflag & MY_CHECK_ERROR prints if some files are left open
|
||||||
|
- If infoflag & MY_GIVE_INFO prints timing info and malloc info
|
||||||
|
about prog.
|
||||||
|
|
||||||
|
int my_redel _A((const char *from, const char *to, int MyFlags));
|
||||||
|
- Delete from before rename of to to from. Copyes state from old
|
||||||
|
file to new file. If MY_COPY_TIME is set sets old time.
|
||||||
|
|
||||||
|
int my_copystat _A((const char *from, const char *to, int MyFlags));
|
||||||
|
- Copye state from old file to new file.
|
||||||
|
If MY_COPY_TIME is set sets copy also time.
|
||||||
|
|
||||||
|
string my_filename _A((File fd));
|
||||||
|
- Give filename of open file.
|
||||||
|
|
||||||
|
int dirname _A((string to,const char *name));
|
||||||
|
- Copy name of directory from filename.
|
||||||
|
|
||||||
|
int test_if_hard_path _A((const char *dir_name));
|
||||||
|
- Test if dirname is a hard path (Starts from root)
|
||||||
|
|
||||||
|
void convert_dirname _A((string name));
|
||||||
|
- Convert dirname acording to system.
|
||||||
|
- In MSDOS changes all caracters to capitals and changes '/' to
|
||||||
|
'\'
|
||||||
|
string fn_ext _A((const char *name));
|
||||||
|
- Returns pointer to extension in filename
|
||||||
|
string fn_format _A((string to,const char *name,const char *dsk,
|
||||||
|
const char *form,int flag));
|
||||||
|
format a filename with replace of library and extension and
|
||||||
|
converts between different systems.
|
||||||
|
params to and name may be identicall
|
||||||
|
function dosn't change name if name != to
|
||||||
|
Flag may be: 1 force replace filnames library with 'dsk'
|
||||||
|
2 force replace extension with 'form' */
|
||||||
|
4 force Unpack filename (replace ~ with home)
|
||||||
|
8 Pack filename as short as possibly for output to
|
||||||
|
user.
|
||||||
|
All open requests should allways use at least:
|
||||||
|
"open(fn_format(temp_buffe,name,"","",4),...)" to unpack home and
|
||||||
|
convert filename to system-form.
|
||||||
|
|
||||||
|
string fn_same _A((string toname,const char *name,int flag));
|
||||||
|
- Copys directory and extension from name to toname if neaded.
|
||||||
|
copy can be forced by same flags that in fn_format.
|
||||||
|
|
||||||
|
int wild_compare _A((const char *str,const char *wildstr));
|
||||||
|
- Compare if str matches wildstr. Wildstr can contain "*" and "?"
|
||||||
|
as match-characters.
|
||||||
|
Returns 0 if match.
|
||||||
|
|
||||||
|
void get_date _A((string to,int timeflag));
|
||||||
|
- Get current date in a form ready for printing.
|
||||||
|
|
||||||
|
void soundex _A((string out_pntr, string in_pntr))
|
||||||
|
- Makes in_pntr to a 5 chars long string. All words that sounds
|
||||||
|
alike have the same string.
|
||||||
|
|
||||||
|
int init_key_cache _A((ulong use_mem,ulong leave_this_much_mem));
|
||||||
|
- Use cacheing of keys in MISAM, PISAM, and ISAM.
|
||||||
|
KEY_CACHE_SIZE is a good size.
|
||||||
|
- Remember to lock databases for optimal cacheing
|
||||||
|
|
||||||
|
void end_key_cache _A((void));
|
||||||
|
- End key-cacheing.
|
@ -453,3 +453,5 @@
|
|||||||
"Mixing of transactional and non-transactional tables is disabled",
|
"Mixing of transactional and non-transactional tables is disabled",
|
||||||
#define ER_DUP_ARGUMENT 225
|
#define ER_DUP_ARGUMENT 225
|
||||||
"Option '%s' used twice in statement",
|
"Option '%s' used twice in statement",
|
||||||
|
#define ER_TOO_MANY_USER_CONNECTIONS 203
|
||||||
|
"User %-.64s has already more than 'max_user_connections' active connections",
|
||||||
|
@ -2276,9 +2276,9 @@ AC_OUTPUT(Makefile extra/Makefile mysys/Makefile isam/Makefile \
|
|||||||
include/mysql_version.h
|
include/mysql_version.h
|
||||||
, , [
|
, , [
|
||||||
test -z "$CONFIG_HEADERS" || echo timestamp > stamp-h
|
test -z "$CONFIG_HEADERS" || echo timestamp > stamp-h
|
||||||
rm -f $AVAILABLE_LANGUAGES_ERRORS_RULES
|
|
||||||
])
|
])
|
||||||
|
|
||||||
|
rm -f $AVAILABLE_LANGUAGES_ERRORS_RULES
|
||||||
echo
|
echo
|
||||||
echo "MySQL has a Web site at http://www.mysql.com/ which carries details on the"
|
echo "MySQL has a Web site at http://www.mysql.com/ which carries details on the"
|
||||||
echo "latest release, upcoming features, and other information to make your"
|
echo "latest release, upcoming features, and other information to make your"
|
||||||
@ -2288,6 +2288,6 @@ echo
|
|||||||
echo "Remember to check the platform specific part in the reference manual for"
|
echo "Remember to check the platform specific part in the reference manual for"
|
||||||
echo "hints about installing on your platfrom. See the Docs directory."
|
echo "hints about installing on your platfrom. See the Docs directory."
|
||||||
echo
|
echo
|
||||||
# This text is checked in ./Do-compile to se that the configure finished.
|
# The following text is checked in ./Do-compile to se that the configure ends.
|
||||||
echo "Thank you for choosing MySQL!"
|
echo "Thank you for choosing MySQL!"
|
||||||
echo
|
echo
|
||||||
|
@ -35,10 +35,10 @@ struct my_option
|
|||||||
enum get_opt_var_type var_type;
|
enum get_opt_var_type var_type;
|
||||||
enum get_opt_arg_type arg_type;
|
enum get_opt_arg_type arg_type;
|
||||||
int id; /* unique id or short option */
|
int id; /* unique id or short option */
|
||||||
long long def_value; /* Default value */
|
longlong def_value; /* Default value */
|
||||||
long long min_value; /* Min allowed value */
|
longlong min_value; /* Min allowed value */
|
||||||
long long max_value; /* Max allowed value */
|
longlong max_value; /* Max allowed value */
|
||||||
long long sub_size; /* Subtract this from given value */
|
longlong sub_size; /* Subtract this from given value */
|
||||||
long block_size; /* Value should be a mult. of this */
|
long block_size; /* Value should be a mult. of this */
|
||||||
int app_type; /* To be used by an application */
|
int app_type; /* To be used by an application */
|
||||||
my_bool changeable_var; /* If true, the option is a variable */
|
my_bool changeable_var; /* If true, the option is a variable */
|
||||||
|
@ -51,7 +51,8 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif /* _WIN32... */
|
#endif /* _WIN32... */
|
||||||
|
|
||||||
/* The macros below are borrowed from include/linux/compiler.h in the
|
/*
|
||||||
|
The macros below are borrowed from include/linux/compiler.h in the
|
||||||
Linux kernel. Use them to indicate the likelyhood of the truthfulness
|
Linux kernel. Use them to indicate the likelyhood of the truthfulness
|
||||||
of a condition. This serves two purposes - newer versions of gcc will be
|
of a condition. This serves two purposes - newer versions of gcc will be
|
||||||
able to optimize for branch predication, which could yield siginficant
|
able to optimize for branch predication, which could yield siginficant
|
||||||
@ -59,7 +60,7 @@
|
|||||||
other reason to use them is for documentation
|
other reason to use them is for documentation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if __GNUC__ == 2 && __GNUC_MINOR__ < 96
|
#if !defined(__GNUC__) || (__GNUC__ == 2 && __GNUC_MINOR__ < 96)
|
||||||
#define __builtin_expect(x, expected_value) (x)
|
#define __builtin_expect(x, expected_value) (x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -242,4 +242,5 @@
|
|||||||
#define ER_CANT_UPDATE_WITH_READLOCK 1223
|
#define ER_CANT_UPDATE_WITH_READLOCK 1223
|
||||||
#define ER_MIXING_NOT_ALLOWED 1224
|
#define ER_MIXING_NOT_ALLOWED 1224
|
||||||
#define ER_DUP_ARGUMENT 1225
|
#define ER_DUP_ARGUMENT 1225
|
||||||
#define ER_ERROR_MESSAGES 226
|
#define ER_USER_LIMIT_REACHED 1226
|
||||||
|
#define ER_ERROR_MESSAGES 227
|
||||||
|
@ -64,3 +64,15 @@ CAST(CAST(1-2 AS UNSIGNED) AS SIGNED INTEGER)
|
|||||||
select CONVERT('-1',UNSIGNED);
|
select CONVERT('-1',UNSIGNED);
|
||||||
CONVERT('-1',UNSIGNED)
|
CONVERT('-1',UNSIGNED)
|
||||||
18446744073709551615
|
18446744073709551615
|
||||||
|
select cast(-5 as unsigned) | 1, cast(-5 as unsigned) & -1;
|
||||||
|
cast(-5 as unsigned) | 1 cast(-5 as unsigned) & -1
|
||||||
|
18446744073709551611 18446744073709551611
|
||||||
|
select cast(-5 as unsigned) -1, cast(-5 as unsigned) + 1;
|
||||||
|
cast(-5 as unsigned) -1 cast(-5 as unsigned) + 1
|
||||||
|
18446744073709551610 18446744073709551612
|
||||||
|
select ~5, cast(~5 as signed);
|
||||||
|
~5 cast(~5 as signed)
|
||||||
|
18446744073709551610 -6
|
||||||
|
select cast(5 as unsigned) -6.0;
|
||||||
|
cast(5 as unsigned) -6.0
|
||||||
|
-1.0
|
||||||
|
@ -6,4 +6,4 @@ select 1 | (1+1),5 & 3,bit_count(7) ;
|
|||||||
3 1 3
|
3 1 3
|
||||||
select 1 << 32,1 << 63, 1 << 64, 4 >> 2, 4 >> 63, 1<< 63 >> 60;
|
select 1 << 32,1 << 63, 1 << 64, 4 >> 2, 4 >> 63, 1<< 63 >> 60;
|
||||||
1 << 32 1 << 63 1 << 64 4 >> 2 4 >> 63 1<< 63 >> 60
|
1 << 32 1 << 63 1 << 64 4 >> 2 4 >> 63 1<< 63 >> 60
|
||||||
4294967296 -9223372036854775808 0 1 0 8
|
4294967296 9223372036854775808 0 1 0 8
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
select 0x41,0x41+0,0x41 | 0x7fffffffffffffff | 0,0xffffffffffffffff | 0 ;
|
select 0x41,0x41+0,0x41 | 0x7fffffffffffffff | 0,0xffffffffffffffff | 0 ;
|
||||||
0x41 0x41+0 0x41 | 0x7fffffffffffffff | 0 0xffffffffffffffff | 0
|
0x41 0x41+0 0x41 | 0x7fffffffffffffff | 0 0xffffffffffffffff | 0
|
||||||
A 65 9223372036854775807 -1
|
A 65 9223372036854775807 18446744073709551615
|
||||||
select 0x31+1,concat(0x31)+1,-0xf;
|
select 0x31+1,concat(0x31)+1,-0xf;
|
||||||
0x31+1 concat(0x31)+1 -0xf
|
0x31+1 concat(0x31)+1 -0xf
|
||||||
50 2 -15
|
50 2 -15
|
||||||
|
@ -33,3 +33,7 @@ drop table t1;
|
|||||||
select CAST(1-2 AS UNSIGNED);
|
select CAST(1-2 AS UNSIGNED);
|
||||||
select CAST(CAST(1-2 AS UNSIGNED) AS SIGNED INTEGER);
|
select CAST(CAST(1-2 AS UNSIGNED) AS SIGNED INTEGER);
|
||||||
select CONVERT('-1',UNSIGNED);
|
select CONVERT('-1',UNSIGNED);
|
||||||
|
select cast(-5 as unsigned) | 1, cast(-5 as unsigned) & -1;
|
||||||
|
select cast(-5 as unsigned) -1, cast(-5 as unsigned) + 1;
|
||||||
|
select ~5, cast(~5 as signed);
|
||||||
|
select cast(5 as unsigned) -6.0;
|
||||||
|
@ -180,15 +180,15 @@ class Item_num_op :public Item_func
|
|||||||
class Item_int_func :public Item_func
|
class Item_int_func :public Item_func
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Item_int_func() :Item_func() {}
|
Item_int_func() :Item_func() { max_length=21; }
|
||||||
Item_int_func(Item *a) :Item_func(a) {}
|
Item_int_func(Item *a) :Item_func(a) { max_length=21; }
|
||||||
Item_int_func(Item *a,Item *b) :Item_func(a,b) {}
|
Item_int_func(Item *a,Item *b) :Item_func(a,b) { max_length=21; }
|
||||||
Item_int_func(Item *a,Item *b,Item *c) :Item_func(a,b,c) {}
|
Item_int_func(Item *a,Item *b,Item *c) :Item_func(a,b,c) { max_length=21; }
|
||||||
Item_int_func(List<Item> &list) :Item_func(list) {}
|
Item_int_func(List<Item> &list) :Item_func(list) { max_length=21; }
|
||||||
double val() { return (double) val_int(); }
|
double val() { return (double) val_int(); }
|
||||||
String *val_str(String*str);
|
String *val_str(String*str);
|
||||||
enum Item_result result_type () const { return INT_RESULT; }
|
enum Item_result result_type () const { return INT_RESULT; }
|
||||||
void fix_length_and_dec() { decimals=0; max_length=21; }
|
void fix_length_and_dec() {}
|
||||||
Field *tmp_table_field(TABLE *t_arg)
|
Field *tmp_table_field(TABLE *t_arg)
|
||||||
{
|
{
|
||||||
if (!t_arg) return result_field;
|
if (!t_arg) return result_field;
|
||||||
@ -203,7 +203,7 @@ public:
|
|||||||
double val() { return args[0]->val(); }
|
double val() { return args[0]->val(); }
|
||||||
longlong val_int() { return args[0]->val_int(); }
|
longlong val_int() { return args[0]->val_int(); }
|
||||||
void fix_length_and_dec()
|
void fix_length_and_dec()
|
||||||
{ decimals=0; max_length=args[0]->max_length; unsigned_flag=0; }
|
{ max_length=args[0]->max_length; unsigned_flag=0; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class Item_func_unsigned :public Item_int_func
|
class Item_func_unsigned :public Item_int_func
|
||||||
@ -213,7 +213,7 @@ public:
|
|||||||
double val() { return args[0]->val(); }
|
double val() { return args[0]->val(); }
|
||||||
longlong val_int() { return args[0]->val_int(); }
|
longlong val_int() { return args[0]->val_int(); }
|
||||||
void fix_length_and_dec()
|
void fix_length_and_dec()
|
||||||
{ decimals=0; max_length=args[0]->max_length; unsigned_flag=1; }
|
{ max_length=args[0]->max_length; unsigned_flag=1; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -598,7 +598,6 @@ public:
|
|||||||
Item_func_ord(Item *a) :Item_int_func(a) {}
|
Item_func_ord(Item *a) :Item_int_func(a) {}
|
||||||
longlong val_int();
|
longlong val_int();
|
||||||
const char *func_name() const { return "ord"; }
|
const char *func_name() const { return "ord"; }
|
||||||
void fix_length_and_dec() { max_length=21; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Item_func_find_in_set :public Item_int_func
|
class Item_func_find_in_set :public Item_int_func
|
||||||
@ -620,7 +619,7 @@ public:
|
|||||||
Item_func_bit_or(Item *a,Item *b) :Item_int_func(a,b) {}
|
Item_func_bit_or(Item *a,Item *b) :Item_int_func(a,b) {}
|
||||||
longlong val_int();
|
longlong val_int();
|
||||||
const char *func_name() const { return "|"; }
|
const char *func_name() const { return "|"; }
|
||||||
void fix_length_and_dec() { decimals=0; max_length=21; }
|
void fix_length_and_dec() { unsigned_flag=1; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class Item_func_bit_and :public Item_int_func
|
class Item_func_bit_and :public Item_int_func
|
||||||
@ -629,7 +628,7 @@ public:
|
|||||||
Item_func_bit_and(Item *a,Item *b) :Item_int_func(a,b) {}
|
Item_func_bit_and(Item *a,Item *b) :Item_int_func(a,b) {}
|
||||||
longlong val_int();
|
longlong val_int();
|
||||||
const char *func_name() const { return "&"; }
|
const char *func_name() const { return "&"; }
|
||||||
void fix_length_and_dec() { decimals=0; max_length=21; }
|
void fix_length_and_dec() { unsigned_flag=1; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class Item_func_bit_count :public Item_int_func
|
class Item_func_bit_count :public Item_int_func
|
||||||
@ -638,7 +637,7 @@ public:
|
|||||||
Item_func_bit_count(Item *a) :Item_int_func(a) {}
|
Item_func_bit_count(Item *a) :Item_int_func(a) {}
|
||||||
longlong val_int();
|
longlong val_int();
|
||||||
const char *func_name() const { return "bit_count"; }
|
const char *func_name() const { return "bit_count"; }
|
||||||
void fix_length_and_dec() { decimals=0; max_length=2; }
|
void fix_length_and_dec() { max_length=2; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class Item_func_shift_left :public Item_int_func
|
class Item_func_shift_left :public Item_int_func
|
||||||
@ -647,7 +646,7 @@ public:
|
|||||||
Item_func_shift_left(Item *a,Item *b) :Item_int_func(a,b) {}
|
Item_func_shift_left(Item *a,Item *b) :Item_int_func(a,b) {}
|
||||||
longlong val_int();
|
longlong val_int();
|
||||||
const char *func_name() const { return "<<"; }
|
const char *func_name() const { return "<<"; }
|
||||||
void fix_length_and_dec() { decimals=0; max_length=21; }
|
void fix_length_and_dec() { unsigned_flag=1; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class Item_func_shift_right :public Item_int_func
|
class Item_func_shift_right :public Item_int_func
|
||||||
@ -656,7 +655,6 @@ public:
|
|||||||
Item_func_shift_right(Item *a,Item *b) :Item_int_func(a,b) {}
|
Item_func_shift_right(Item *a,Item *b) :Item_int_func(a,b) {}
|
||||||
longlong val_int();
|
longlong val_int();
|
||||||
const char *func_name() const { return ">>"; }
|
const char *func_name() const { return ">>"; }
|
||||||
void fix_length_and_dec() { decimals=0; max_length=21; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Item_func_bit_neg :public Item_int_func
|
class Item_func_bit_neg :public Item_int_func
|
||||||
@ -665,7 +663,7 @@ public:
|
|||||||
Item_func_bit_neg(Item *a) :Item_int_func(a) {}
|
Item_func_bit_neg(Item *a) :Item_int_func(a) {}
|
||||||
longlong val_int();
|
longlong val_int();
|
||||||
const char *func_name() const { return "~"; }
|
const char *func_name() const { return "~"; }
|
||||||
void fix_length_and_dec() { decimals=0; max_length=21; }
|
void fix_length_and_dec() { unsigned_flag=1; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class Item_func_set_last_insert_id :public Item_int_func
|
class Item_func_set_last_insert_id :public Item_int_func
|
||||||
@ -674,7 +672,7 @@ public:
|
|||||||
Item_func_set_last_insert_id(Item *a) :Item_int_func(a) {}
|
Item_func_set_last_insert_id(Item *a) :Item_int_func(a) {}
|
||||||
longlong val_int();
|
longlong val_int();
|
||||||
const char *func_name() const { return "last_insert_id"; }
|
const char *func_name() const { return "last_insert_id"; }
|
||||||
void fix_length_and_dec() { decimals=0; max_length=args[0]->max_length; }
|
void fix_length_and_dec() { max_length=args[0]->max_length; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class Item_func_benchmark :public Item_int_func
|
class Item_func_benchmark :public Item_int_func
|
||||||
@ -686,7 +684,7 @@ class Item_func_benchmark :public Item_int_func
|
|||||||
{}
|
{}
|
||||||
longlong val_int();
|
longlong val_int();
|
||||||
const char *func_name() const { return "benchmark"; }
|
const char *func_name() const { return "benchmark"; }
|
||||||
void fix_length_and_dec() { decimals=0; max_length=1; maybe_null=0; }
|
void fix_length_and_dec() { max_length=1; maybe_null=0; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -818,7 +816,7 @@ class Item_func_get_lock :public Item_int_func
|
|||||||
Item_func_get_lock(Item *a,Item *b) :Item_int_func(a,b) {}
|
Item_func_get_lock(Item *a,Item *b) :Item_int_func(a,b) {}
|
||||||
longlong val_int();
|
longlong val_int();
|
||||||
const char *func_name() const { return "get_lock"; }
|
const char *func_name() const { return "get_lock"; }
|
||||||
void fix_length_and_dec() { decimals=0; max_length=1; maybe_null=1;}
|
void fix_length_and_dec() { max_length=1; maybe_null=1;}
|
||||||
};
|
};
|
||||||
|
|
||||||
class Item_func_release_lock :public Item_int_func
|
class Item_func_release_lock :public Item_int_func
|
||||||
@ -828,7 +826,7 @@ class Item_func_release_lock :public Item_int_func
|
|||||||
Item_func_release_lock(Item *a) :Item_int_func(a) {}
|
Item_func_release_lock(Item *a) :Item_int_func(a) {}
|
||||||
longlong val_int();
|
longlong val_int();
|
||||||
const char *func_name() const { return "release_lock"; }
|
const char *func_name() const { return "release_lock"; }
|
||||||
void fix_length_and_dec() { decimals=0; max_length=1; maybe_null=1;}
|
void fix_length_and_dec() { max_length=1; maybe_null=1;}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* replication functions */
|
/* replication functions */
|
||||||
@ -840,7 +838,7 @@ class Item_master_pos_wait :public Item_int_func
|
|||||||
Item_master_pos_wait(Item *a,Item *b) :Item_int_func(a,b) {}
|
Item_master_pos_wait(Item *a,Item *b) :Item_int_func(a,b) {}
|
||||||
longlong val_int();
|
longlong val_int();
|
||||||
const char *func_name() const { return "master_pos_wait"; }
|
const char *func_name() const { return "master_pos_wait"; }
|
||||||
void fix_length_and_dec() { decimals=0; max_length=1; maybe_null=1;}
|
void fix_length_and_dec() { max_length=1; maybe_null=1;}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -431,10 +431,11 @@ int lock_table_name(THD *thd, TABLE_LIST *table_list)
|
|||||||
if (table->in_use == thd)
|
if (table->in_use == thd)
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
|
|
||||||
/* Create a table entry with the right key and with an old refresh version */
|
/*
|
||||||
/* Note that we must use my_malloc() here as this is freed by the table
|
Create a table entry with the right key and with an old refresh version
|
||||||
cache */
|
Note that we must use my_malloc() here as this is freed by the table
|
||||||
|
cache
|
||||||
|
*/
|
||||||
if (!(table= (TABLE*) my_malloc(sizeof(*table)+key_length,
|
if (!(table= (TABLE*) my_malloc(sizeof(*table)+key_length,
|
||||||
MYF(MY_WME | MY_ZEROFILL))))
|
MYF(MY_WME | MY_ZEROFILL))))
|
||||||
DBUG_RETURN(-1);
|
DBUG_RETURN(-1);
|
||||||
|
45
sql/log.cc
45
sql/log.cc
@ -370,6 +370,7 @@ err:
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int MYSQL_LOG::reset_logs(THD* thd)
|
int MYSQL_LOG::reset_logs(THD* thd)
|
||||||
{
|
{
|
||||||
LOG_INFO linfo;
|
LOG_INFO linfo;
|
||||||
@ -403,6 +404,7 @@ err:
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int MYSQL_LOG::purge_first_log(struct st_relay_log_info* rli)
|
int MYSQL_LOG::purge_first_log(struct st_relay_log_info* rli)
|
||||||
{
|
{
|
||||||
// pre-conditions
|
// pre-conditions
|
||||||
@ -410,17 +412,17 @@ int MYSQL_LOG::purge_first_log(struct st_relay_log_info* rli)
|
|||||||
DBUG_ASSERT(index_file >= 0);
|
DBUG_ASSERT(index_file >= 0);
|
||||||
DBUG_ASSERT(rli->slave_running == 1);
|
DBUG_ASSERT(rli->slave_running == 1);
|
||||||
DBUG_ASSERT(!strcmp(rli->linfo.log_file_name,rli->relay_log_name));
|
DBUG_ASSERT(!strcmp(rli->linfo.log_file_name,rli->relay_log_name));
|
||||||
// assume that we have previously read the first log and
|
/*
|
||||||
// stored it in rli->relay_log_name
|
Assume that we have previously read the first log and
|
||||||
|
stored it in rli->relay_log_name
|
||||||
|
*/
|
||||||
DBUG_ASSERT(rli->linfo.index_file_offset ==
|
DBUG_ASSERT(rli->linfo.index_file_offset ==
|
||||||
strlen(rli->relay_log_name) + 1);
|
strlen(rli->relay_log_name) + 1);
|
||||||
|
|
||||||
int tmp_fd;
|
int tmp_fd;
|
||||||
|
|
||||||
|
|
||||||
char* fname, *io_buf;
|
char* fname, *io_buf;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
if (!(fname = (char*)my_malloc(IO_SIZE+FN_REFLEN, MYF(MY_WME))))
|
|
||||||
|
if (!(fname= (char*) my_malloc(IO_SIZE+FN_REFLEN, MYF(MY_WME))))
|
||||||
return 1;
|
return 1;
|
||||||
pthread_mutex_lock(&LOCK_index);
|
pthread_mutex_lock(&LOCK_index);
|
||||||
my_seek(index_file,rli->linfo.index_file_offset,
|
my_seek(index_file,rli->linfo.index_file_offset,
|
||||||
@ -436,7 +438,7 @@ int MYSQL_LOG::purge_first_log(struct st_relay_log_info* rli)
|
|||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
int bytes_read;
|
int bytes_read;
|
||||||
bytes_read = my_read(index_file, io_buf, IO_SIZE, MYF(0));
|
bytes_read = my_read(index_file, (byte*) io_buf, IO_SIZE, MYF(0));
|
||||||
if (bytes_read < 0) // error
|
if (bytes_read < 0) // error
|
||||||
{
|
{
|
||||||
error=1;
|
error=1;
|
||||||
@ -445,12 +447,13 @@ int MYSQL_LOG::purge_first_log(struct st_relay_log_info* rli)
|
|||||||
if (!bytes_read)
|
if (!bytes_read)
|
||||||
break; // end of file
|
break; // end of file
|
||||||
// otherwise, we've read something and need to write it out
|
// otherwise, we've read something and need to write it out
|
||||||
if (my_write(tmp_fd, io_buf, bytes_read, MYF(MY_WME|MY_NABP)))
|
if (my_write(tmp_fd, (byte*) io_buf, bytes_read, MYF(MY_WME|MY_NABP)))
|
||||||
{
|
{
|
||||||
error=1;
|
error=1;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err:
|
err:
|
||||||
if (tmp_fd)
|
if (tmp_fd)
|
||||||
my_close(tmp_fd, MYF(MY_WME));
|
my_close(tmp_fd, MYF(MY_WME));
|
||||||
@ -476,18 +479,20 @@ err:
|
|||||||
strnmov(rli->relay_log_name,rli->linfo.log_file_name,
|
strnmov(rli->relay_log_name,rli->linfo.log_file_name,
|
||||||
sizeof(rli->relay_log_name));
|
sizeof(rli->relay_log_name));
|
||||||
}
|
}
|
||||||
// no need to free io_buf because we allocated both fname and io_buf in
|
/*
|
||||||
// one malloc()
|
No need to free io_buf because we allocated both fname and io_buf in
|
||||||
|
one malloc()
|
||||||
|
*/
|
||||||
|
|
||||||
err2:
|
err2:
|
||||||
pthread_mutex_unlock(&LOCK_index);
|
pthread_mutex_unlock(&LOCK_index);
|
||||||
my_free(fname, MYF(MY_WME));
|
my_free(fname, MYF(MY_WME));
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int MYSQL_LOG::purge_logs(THD* thd, const char* to_log)
|
int MYSQL_LOG::purge_logs(THD* thd, const char* to_log)
|
||||||
{
|
{
|
||||||
if (index_file < 0) return LOG_INFO_INVALID;
|
|
||||||
if (no_rotate) return LOG_INFO_PURGE_NO_ROTATE;
|
|
||||||
int error;
|
int error;
|
||||||
char fname[FN_REFLEN];
|
char fname[FN_REFLEN];
|
||||||
char *p;
|
char *p;
|
||||||
@ -498,6 +503,10 @@ int MYSQL_LOG::purge_logs(THD* thd, const char* to_log)
|
|||||||
LINT_INIT(purge_offset);
|
LINT_INIT(purge_offset);
|
||||||
IO_CACHE io_cache;
|
IO_CACHE io_cache;
|
||||||
|
|
||||||
|
if (index_file < 0)
|
||||||
|
return LOG_INFO_INVALID;
|
||||||
|
if (no_rotate)
|
||||||
|
return LOG_INFO_PURGE_NO_ROTATE;
|
||||||
pthread_mutex_lock(&LOCK_index);
|
pthread_mutex_lock(&LOCK_index);
|
||||||
|
|
||||||
if (init_io_cache(&io_cache,index_file, IO_SIZE*2, READ_CACHE, (my_off_t) 0,
|
if (init_io_cache(&io_cache,index_file, IO_SIZE*2, READ_CACHE, (my_off_t) 0,
|
||||||
@ -569,9 +578,10 @@ int MYSQL_LOG::purge_logs(THD* thd, const char* to_log)
|
|||||||
sql_print_error("Error deleting %s during purge", l);
|
sql_print_error("Error deleting %s during purge", l);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we get killed -9 here, the sysadmin would have to do a small
|
/*
|
||||||
// vi job on the log index file after restart - otherwise, this should
|
If we get killed -9 here, the sysadmin would have to edit
|
||||||
// be safe
|
the log index file after restart - otherwise, this should be safe
|
||||||
|
*/
|
||||||
#ifdef HAVE_FTRUNCATE
|
#ifdef HAVE_FTRUNCATE
|
||||||
if (ftruncate(index_file,0))
|
if (ftruncate(index_file,0))
|
||||||
{
|
{
|
||||||
@ -737,14 +747,14 @@ bool MYSQL_LOG::appendv(const char* buf, uint len,...)
|
|||||||
pthread_mutex_lock(&LOCK_log);
|
pthread_mutex_lock(&LOCK_log);
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if (my_b_append(&log_file,buf,len))
|
if (my_b_append(&log_file,(byte*) buf,len))
|
||||||
{
|
{
|
||||||
error = 1;
|
error = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} while ((buf=va_arg(args,const char*)) && (len=va_arg(args,uint)));
|
} while ((buf=va_arg(args,const char*)) && (len=va_arg(args,uint)));
|
||||||
|
|
||||||
if ((uint)my_b_append_tell(&log_file) > max_binlog_size)
|
if ((uint) my_b_append_tell(&log_file) > max_binlog_size)
|
||||||
{
|
{
|
||||||
new_file(1);
|
new_file(1);
|
||||||
}
|
}
|
||||||
@ -755,6 +765,7 @@ bool MYSQL_LOG::appendv(const char* buf, uint len,...)
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool MYSQL_LOG::write(THD *thd,enum enum_server_command command,
|
bool MYSQL_LOG::write(THD *thd,enum enum_server_command command,
|
||||||
const char *format,...)
|
const char *format,...)
|
||||||
{
|
{
|
||||||
|
@ -26,17 +26,19 @@
|
|||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
inline int my_b_safe_write(IO_CACHE* file, const char* buf,
|
inline int my_b_safe_write(IO_CACHE* file, const byte *buf,
|
||||||
int len)
|
int len)
|
||||||
{
|
{
|
||||||
// Sasha: We are not writing this with the ? operator to avoid hitting
|
/*
|
||||||
// a possible compiler bug. At least gcc 2.95 cannot deal with
|
Sasha: We are not writing this with the ? operator to avoid hitting
|
||||||
// several layers of ternary operators that evaluated comma(,) operator
|
a possible compiler bug. At least gcc 2.95 cannot deal with
|
||||||
// expressions inside - I do have a test case if somebody wants it
|
several layers of ternary operators that evaluated comma(,) operator
|
||||||
|
expressions inside - I do have a test case if somebody wants it
|
||||||
|
*/
|
||||||
if (file->type == SEQ_READ_APPEND)
|
if (file->type == SEQ_READ_APPEND)
|
||||||
return my_b_append(file,buf,len);
|
return my_b_append(file, buf,len);
|
||||||
return my_b_write(file,buf,len);
|
return my_b_write(file, buf,len);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MYSQL_CLIENT
|
#ifdef MYSQL_CLIENT
|
||||||
static void pretty_print_str(FILE* file, char* str, int len)
|
static void pretty_print_str(FILE* file, char* str, int len)
|
||||||
@ -94,6 +96,7 @@ static void pretty_print_str(String* packet, char* str, int len)
|
|||||||
packet->append('\'');
|
packet->append('\'');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline char* slave_load_file_stem(char*buf, uint file_id,
|
static inline char* slave_load_file_stem(char*buf, uint file_id,
|
||||||
int event_server_id)
|
int event_server_id)
|
||||||
{
|
{
|
||||||
@ -382,9 +385,9 @@ int Log_event::net_send(THD* thd, const char* log_name, my_off_t pos)
|
|||||||
event_type = get_type_str();
|
event_type = get_type_str();
|
||||||
net_store_data(packet, event_type, strlen(event_type));
|
net_store_data(packet, event_type, strlen(event_type));
|
||||||
net_store_data(packet, server_id);
|
net_store_data(packet, server_id);
|
||||||
net_store_data(packet, log_pos);
|
net_store_data(packet, (longlong) log_pos);
|
||||||
pack_info(packet);
|
pack_info(packet);
|
||||||
return my_net_write(&thd->net, (char*)packet->ptr(), packet->length());
|
return my_net_write(&thd->net, (char*) packet->ptr(), packet->length());
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@ -1218,30 +1221,29 @@ void Load_log_event::set_fields(List<Item> &fields)
|
|||||||
{
|
{
|
||||||
uint i;
|
uint i;
|
||||||
const char* field = this->fields;
|
const char* field = this->fields;
|
||||||
for(i = 0; i < num_fields; i++)
|
for (i = 0; i < num_fields; i++)
|
||||||
{
|
{
|
||||||
fields.push_back(new Item_field(db, table_name, field));
|
fields.push_back(new Item_field(db, table_name, field));
|
||||||
field += field_lens[i] + 1;
|
field += field_lens[i] + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Slave_log_event::Slave_log_event(THD* thd_arg,
|
Slave_log_event::Slave_log_event(THD* thd_arg,
|
||||||
struct st_relay_log_info* rli):
|
struct st_relay_log_info* rli):
|
||||||
Log_event(thd_arg),mem_pool(0),master_host(0)
|
Log_event(thd_arg),mem_pool(0),master_host(0)
|
||||||
{
|
{
|
||||||
if(!rli->inited)
|
if (!rli->inited)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
MASTER_INFO* mi = rli->mi;
|
MASTER_INFO* mi = rli->mi;
|
||||||
// TODO: re-write this better without holding both
|
// TODO: re-write this better without holding both locks at the same time
|
||||||
// locks at the same time
|
|
||||||
pthread_mutex_lock(&mi->data_lock);
|
pthread_mutex_lock(&mi->data_lock);
|
||||||
pthread_mutex_lock(&rli->data_lock);
|
pthread_mutex_lock(&rli->data_lock);
|
||||||
master_host_len = strlen(mi->host);
|
master_host_len = strlen(mi->host);
|
||||||
master_log_len = strlen(rli->master_log_name);
|
master_log_len = strlen(rli->master_log_name);
|
||||||
// on OOM, just do not initialize the structure and print the error
|
// on OOM, just do not initialize the structure and print the error
|
||||||
if((mem_pool = (char*)my_malloc(get_data_size() + 1,
|
if ((mem_pool = (char*)my_malloc(get_data_size() + 1,
|
||||||
MYF(MY_WME))))
|
MYF(MY_WME))))
|
||||||
{
|
{
|
||||||
master_host = mem_pool + SL_MASTER_HOST_OFFSET ;
|
master_host = mem_pool + SL_MASTER_HOST_OFFSET ;
|
||||||
@ -1276,8 +1278,8 @@ void Slave_log_event::print(FILE* file, bool short_form, char* last_db)
|
|||||||
print_header(file);
|
print_header(file);
|
||||||
fputc('\n', file);
|
fputc('\n', file);
|
||||||
fprintf(file, "Slave: master_host='%s' master_port=%d \
|
fprintf(file, "Slave: master_host='%s' master_port=%d \
|
||||||
master_log=%s master_pos=%s\n", master_host, master_port, master_log,
|
master_log=%s master_pos=%s\n",
|
||||||
llstr(master_pos, llbuff));
|
master_host, master_port, master_log, llstr(master_pos, llbuff));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@ -1753,11 +1755,13 @@ int Stop_log_event::exec_event(struct st_relay_log_info* rli)
|
|||||||
close_temporary_tables(thd);
|
close_temporary_tables(thd);
|
||||||
cleanup_load_tmpdir();
|
cleanup_load_tmpdir();
|
||||||
}
|
}
|
||||||
// we do not want to update master_log pos because we get a rotate event
|
/*
|
||||||
// before stop, so by now master_log_name is set to the next log
|
We do not want to update master_log pos because we get a rotate event
|
||||||
// if we updated it, we will have incorrect master coordinates and this
|
before stop, so by now master_log_name is set to the next log
|
||||||
// could give false triggers in MASTER_POS_WAIT() that we have reached
|
if we updated it, we will have incorrect master coordinates and this
|
||||||
// the targed position when in fact we have not
|
could give false triggers in MASTER_POS_WAIT() that we have reached
|
||||||
|
the targed position when in fact we have not
|
||||||
|
*/
|
||||||
rli->inc_pos(get_event_len(), 0);
|
rli->inc_pos(get_event_len(), 0);
|
||||||
flush_relay_log_info(rli);
|
flush_relay_log_info(rli);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -214,7 +214,7 @@ public:
|
|||||||
time_t when;
|
time_t when;
|
||||||
ulong exec_time;
|
ulong exec_time;
|
||||||
uint32 server_id;
|
uint32 server_id;
|
||||||
uint32 log_pos;
|
my_off_t log_pos;
|
||||||
uint16 flags;
|
uint16 flags;
|
||||||
int cached_event_len;
|
int cached_event_len;
|
||||||
char* temp_buf;
|
char* temp_buf;
|
||||||
@ -351,12 +351,12 @@ protected:
|
|||||||
char* mem_pool;
|
char* mem_pool;
|
||||||
void init_from_mem_pool(int data_size);
|
void init_from_mem_pool(int data_size);
|
||||||
public:
|
public:
|
||||||
|
my_off_t master_pos;
|
||||||
char* master_host;
|
char* master_host;
|
||||||
int master_host_len;
|
|
||||||
uint16 master_port;
|
|
||||||
char* master_log;
|
char* master_log;
|
||||||
|
int master_host_len;
|
||||||
int master_log_len;
|
int master_log_len;
|
||||||
ulonglong master_pos;
|
uint16 master_port;
|
||||||
|
|
||||||
#ifndef MYSQL_CLIENT
|
#ifndef MYSQL_CLIENT
|
||||||
Slave_log_event(THD* thd_arg, struct st_relay_log_info* rli);
|
Slave_log_event(THD* thd_arg, struct st_relay_log_info* rli);
|
||||||
|
@ -399,7 +399,7 @@ max_allowed_packet on this server");
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
char * mc_mysql_error(MYSQL *mysql)
|
char *mc_mysql_error(MYSQL *mysql)
|
||||||
{
|
{
|
||||||
return (mysql)->net.last_error;
|
return (mysql)->net.last_error;
|
||||||
}
|
}
|
||||||
@ -1300,7 +1300,7 @@ void mc_mysql_data_seek(MYSQL_RES *result, my_ulonglong row)
|
|||||||
result->data_cursor = tmp;
|
result->data_cursor = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
MYSQL_ROW mc_mysql_fetch_row(MYSQL_RES *res)
|
MYSQL_ROW STDCALL mc_mysql_fetch_row(MYSQL_RES *res)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("mc_mysql_fetch_row");
|
DBUG_ENTER("mc_mysql_fetch_row");
|
||||||
if (!res->data)
|
if (!res->data)
|
||||||
|
@ -1950,7 +1950,6 @@ The server will not act as a slave.");
|
|||||||
}
|
}
|
||||||
if (!opt_noacl)
|
if (!opt_noacl)
|
||||||
(void) grant_init();
|
(void) grant_init();
|
||||||
if (max_user_connections || mqh_used)
|
|
||||||
init_max_user_conn();
|
init_max_user_conn();
|
||||||
|
|
||||||
#ifdef HAVE_DLOPEN
|
#ifdef HAVE_DLOPEN
|
||||||
|
@ -201,7 +201,7 @@ void end_slave_list()
|
|||||||
|
|
||||||
static int find_target_pos(LEX_MASTER_INFO* mi, IO_CACHE* log, char* errmsg)
|
static int find_target_pos(LEX_MASTER_INFO* mi, IO_CACHE* log, char* errmsg)
|
||||||
{
|
{
|
||||||
uint32 log_pos = mi->pos;
|
uint32 log_pos = (uint32) mi->pos;
|
||||||
uint32 target_server_id = mi->server_id;
|
uint32 target_server_id = mi->server_id;
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
@ -799,8 +799,7 @@ int load_master_data(THD* thd)
|
|||||||
{
|
{
|
||||||
strmake(active_mi->master_log_name, row[0],
|
strmake(active_mi->master_log_name, row[0],
|
||||||
sizeof(active_mi->master_log_name));
|
sizeof(active_mi->master_log_name));
|
||||||
// atoi() is ok, since offset is <= 1GB
|
active_mi->master_log_pos = strtoull(row[1], (char**) 0, 10);
|
||||||
active_mi->master_log_pos = atoi(row[1]);
|
|
||||||
if (active_mi->master_log_pos < 4)
|
if (active_mi->master_log_pos < 4)
|
||||||
active_mi->master_log_pos = 4; // don't hit the magic number
|
active_mi->master_log_pos = 4; // don't hit the magic number
|
||||||
active_mi->rli.pending = 0;
|
active_mi->rli.pending = 0;
|
||||||
|
@ -236,3 +236,4 @@
|
|||||||
"Can't execute the query because you have a conflicting read lock",
|
"Can't execute the query because you have a conflicting read lock",
|
||||||
"Mixing of transactional and non-transactional tables is disabled",
|
"Mixing of transactional and non-transactional tables is disabled",
|
||||||
"Option '%s' used twice in statement",
|
"Option '%s' used twice in statement",
|
||||||
|
"User '%-64s' has exceeded the '%s' resource (current value: %ld)",
|
||||||
|
@ -230,3 +230,4 @@
|
|||||||
"Can't execute the query because you have a conflicting read lock",
|
"Can't execute the query because you have a conflicting read lock",
|
||||||
"Mixing of transactional and non-transactional tables is disabled",
|
"Mixing of transactional and non-transactional tables is disabled",
|
||||||
"Option '%s' used twice in statement",
|
"Option '%s' used twice in statement",
|
||||||
|
"User '%-64s' has exceeded the '%s' resource (current value: %ld)",
|
||||||
|
@ -233,3 +233,4 @@
|
|||||||
"Kan de query niet uitvoeren vanwege een conflicterende read lock",
|
"Kan de query niet uitvoeren vanwege een conflicterende read lock",
|
||||||
"Het combineren van transactionele en niet-transactionele tabellen is uitgeschakeld.",
|
"Het combineren van transactionele en niet-transactionele tabellen is uitgeschakeld.",
|
||||||
"Optie '%s' tweemaal gebruikt in opdracht",
|
"Optie '%s' tweemaal gebruikt in opdracht",
|
||||||
|
"User '%-64s' has exceeded the '%s' resource (current value: %ld)",
|
||||||
|
@ -227,3 +227,4 @@
|
|||||||
"Can't execute the query because you have a conflicting read lock",
|
"Can't execute the query because you have a conflicting read lock",
|
||||||
"Mixing of transactional and non-transactional tables is disabled",
|
"Mixing of transactional and non-transactional tables is disabled",
|
||||||
"Option '%s' used twice in statement",
|
"Option '%s' used twice in statement",
|
||||||
|
"User '%-64s' has exceeded the '%s' resource (current value: %ld)",
|
||||||
|
@ -232,3 +232,4 @@
|
|||||||
"Ei suuda t<>ita p<>ringut konfliktse luku t<>ttu",
|
"Ei suuda t<>ita p<>ringut konfliktse luku t<>ttu",
|
||||||
"Transaktsioone toetavate ning mittetoetavate tabelite kooskasutamine ei ole lubatud",
|
"Transaktsioone toetavate ning mittetoetavate tabelite kooskasutamine ei ole lubatud",
|
||||||
"M<><4D>rangut '%s' on lauses kasutatud topelt",
|
"M<><4D>rangut '%s' on lauses kasutatud topelt",
|
||||||
|
"User '%-64s' has exceeded the '%s' resource (current value: %ld)",
|
||||||
|
@ -227,3 +227,4 @@
|
|||||||
"Can't execute the query because you have a conflicting read lock",
|
"Can't execute the query because you have a conflicting read lock",
|
||||||
"Mixing of transactional and non-transactional tables is disabled",
|
"Mixing of transactional and non-transactional tables is disabled",
|
||||||
"Option '%s' used twice in statement",
|
"Option '%s' used twice in statement",
|
||||||
|
"User '%-64s' has exceeded the '%s' resource (current value: %ld)",
|
||||||
|
@ -230,3 +230,4 @@
|
|||||||
"Can't execute the query because you have a conflicting read lock",
|
"Can't execute the query because you have a conflicting read lock",
|
||||||
"Mixing of transactional and non-transactional tables is disabled",
|
"Mixing of transactional and non-transactional tables is disabled",
|
||||||
"Option '%s' used twice in statement",
|
"Option '%s' used twice in statement",
|
||||||
|
"User '%-64s' has exceeded the '%s' resource (current value: %ld)",
|
||||||
|
@ -227,3 +227,4 @@
|
|||||||
"Can't execute the query because you have a conflicting read lock",
|
"Can't execute the query because you have a conflicting read lock",
|
||||||
"Mixing of transactional and non-transactional tables is disabled",
|
"Mixing of transactional and non-transactional tables is disabled",
|
||||||
"Option '%s' used twice in statement",
|
"Option '%s' used twice in statement",
|
||||||
|
"User '%-64s' has exceeded the '%s' resource (current value: %ld)",
|
||||||
|
@ -229,3 +229,4 @@
|
|||||||
"Can't execute the query because you have a conflicting read lock",
|
"Can't execute the query because you have a conflicting read lock",
|
||||||
"Mixing of transactional and non-transactional tables is disabled",
|
"Mixing of transactional and non-transactional tables is disabled",
|
||||||
"Option '%s' used twice in statement",
|
"Option '%s' used twice in statement",
|
||||||
|
"User '%-64s' has exceeded the '%s' resource (current value: %ld)",
|
||||||
|
@ -227,3 +227,4 @@
|
|||||||
"Can't execute the query because you have a conflicting read lock",
|
"Can't execute the query because you have a conflicting read lock",
|
||||||
"Mixing of transactional and non-transactional tables is disabled",
|
"Mixing of transactional and non-transactional tables is disabled",
|
||||||
"Option '%s' used twice in statement",
|
"Option '%s' used twice in statement",
|
||||||
|
"User '%-64s' has exceeded the '%s' resource (current value: %ld)",
|
||||||
|
@ -229,3 +229,4 @@
|
|||||||
"Can't execute the query because you have a conflicting read lock",
|
"Can't execute the query because you have a conflicting read lock",
|
||||||
"Mixing of transactional and non-transactional tables is disabled",
|
"Mixing of transactional and non-transactional tables is disabled",
|
||||||
"Option '%s' used twice in statement",
|
"Option '%s' used twice in statement",
|
||||||
|
"User '%-64s' has exceeded the '%s' resource (current value: %ld)",
|
||||||
|
@ -227,3 +227,4 @@
|
|||||||
"Can't execute the query because you have a conflicting read lock",
|
"Can't execute the query because you have a conflicting read lock",
|
||||||
"Mixing of transactional and non-transactional tables is disabled",
|
"Mixing of transactional and non-transactional tables is disabled",
|
||||||
"Option '%s' used twice in statement",
|
"Option '%s' used twice in statement",
|
||||||
|
"User '%-64s' has exceeded the '%s' resource (current value: %ld)",
|
||||||
|
@ -229,3 +229,4 @@
|
|||||||
"Can't execute the query because you have a conflicting read lock",
|
"Can't execute the query because you have a conflicting read lock",
|
||||||
"Mixing of transactional and non-transactional tables is disabled",
|
"Mixing of transactional and non-transactional tables is disabled",
|
||||||
"Option '%s' used twice in statement",
|
"Option '%s' used twice in statement",
|
||||||
|
"User '%-64s' has exceeded the '%s' resource (current value: %ld)",
|
||||||
|
@ -229,3 +229,4 @@
|
|||||||
"Can't execute the query because you have a conflicting read lock",
|
"Can't execute the query because you have a conflicting read lock",
|
||||||
"Mixing of transactional and non-transactional tables is disabled",
|
"Mixing of transactional and non-transactional tables is disabled",
|
||||||
"Option '%s' used twice in statement",
|
"Option '%s' used twice in statement",
|
||||||
|
"User '%-64s' has exceeded the '%s' resource (current value: %ld)",
|
||||||
|
@ -231,3 +231,4 @@
|
|||||||
"Can't execute the query because you have a conflicting read lock",
|
"Can't execute the query because you have a conflicting read lock",
|
||||||
"Mixing of transactional and non-transactional tables is disabled",
|
"Mixing of transactional and non-transactional tables is disabled",
|
||||||
"Option '%s' used twice in statement",
|
"Option '%s' used twice in statement",
|
||||||
|
"User '%-64s' has exceeded the '%s' resource (current value: %ld)",
|
||||||
|
@ -227,3 +227,4 @@
|
|||||||
"Can't execute the query because you have a conflicting read lock",
|
"Can't execute the query because you have a conflicting read lock",
|
||||||
"Mixing of transactional and non-transactional tables is disabled",
|
"Mixing of transactional and non-transactional tables is disabled",
|
||||||
"Option '%s' used twice in statement",
|
"Option '%s' used twice in statement",
|
||||||
|
"User '%-64s' has exceeded the '%s' resource (current value: %ld)",
|
||||||
|
@ -231,3 +231,4 @@
|
|||||||
"Can't execute the query because you have a conflicting read lock",
|
"Can't execute the query because you have a conflicting read lock",
|
||||||
"Mixing of transactional and non-transactional tables is disabled",
|
"Mixing of transactional and non-transactional tables is disabled",
|
||||||
"Option '%s' used twice in statement",
|
"Option '%s' used twice in statement",
|
||||||
|
"User '%-64s' has exceeded the '%s' resource (current value: %ld)",
|
||||||
|
@ -230,3 +230,4 @@
|
|||||||
"<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>-<2D><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>",
|
"<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>-<2D><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>",
|
||||||
"<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> transactional <20> non-transactional <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>",
|
"<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> transactional <20> non-transactional <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>",
|
||||||
"<22><><EFBFBD><EFBFBD><EFBFBD> '%s' <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>",
|
"<22><><EFBFBD><EFBFBD><EFBFBD> '%s' <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>",
|
||||||
|
"User '%-64s' has exceeded the '%s' resource (current value: %ld)",
|
||||||
|
@ -235,3 +235,4 @@
|
|||||||
"Can't execute the query because you have a conflicting read lock",
|
"Can't execute the query because you have a conflicting read lock",
|
||||||
"Mixing of transactional and non-transactional tables is disabled",
|
"Mixing of transactional and non-transactional tables is disabled",
|
||||||
"Option '%s' used twice in statement",
|
"Option '%s' used twice in statement",
|
||||||
|
"User '%-64s' has exceeded the '%s' resource (current value: %ld)",
|
||||||
|
@ -228,3 +228,4 @@
|
|||||||
"Can't execute the query because you have a conflicting read lock",
|
"Can't execute the query because you have a conflicting read lock",
|
||||||
"Mixing of transactional and non-transactional tables is disabled",
|
"Mixing of transactional and non-transactional tables is disabled",
|
||||||
"Option '%s' used twice in statement",
|
"Option '%s' used twice in statement",
|
||||||
|
"User '%-64s' has exceeded the '%s' resource (current value: %ld)",
|
||||||
|
@ -227,3 +227,4 @@
|
|||||||
"Kan inte utf<74>ra kommandot emedan du har ett READ l<>s",
|
"Kan inte utf<74>ra kommandot emedan du har ett READ l<>s",
|
||||||
"Blandning av transaktionella och icke-transaktionella tabeller <20>r inaktiverat",
|
"Blandning av transaktionella och icke-transaktionella tabeller <20>r inaktiverat",
|
||||||
"Option '%s' anv<6E>ndes tv<74> g<>nger",
|
"Option '%s' anv<6E>ndes tv<74> g<>nger",
|
||||||
|
"Anv<6E>ndare '%-64s' har <20>verskridit '%s' (nuvarande v<>rde: %ld)",
|
||||||
|
@ -232,3 +232,4 @@
|
|||||||
"Can't execute the query because you have a conflicting read lock",
|
"Can't execute the query because you have a conflicting read lock",
|
||||||
"Mixing of transactional and non-transactional tables is disabled",
|
"Mixing of transactional and non-transactional tables is disabled",
|
||||||
"Option '%s' used twice in statement",
|
"Option '%s' used twice in statement",
|
||||||
|
"User '%-64s' has exceeded the '%s' resource (current value: %ld)",
|
||||||
|
211
sql/slave.cc
211
sql/slave.cc
@ -1049,6 +1049,7 @@ err:
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int init_master_info(MASTER_INFO* mi, const char* master_info_fname,
|
int init_master_info(MASTER_INFO* mi, const char* master_info_fname,
|
||||||
const char* slave_info_fname)
|
const char* slave_info_fname)
|
||||||
{
|
{
|
||||||
@ -1058,14 +1059,16 @@ int init_master_info(MASTER_INFO* mi, const char* master_info_fname,
|
|||||||
return 1;
|
return 1;
|
||||||
mi->rli.mi = mi;
|
mi->rli.mi = mi;
|
||||||
mi->ignore_stop_event=0;
|
mi->ignore_stop_event=0;
|
||||||
int fd,length,error;
|
int fd,error;
|
||||||
MY_STAT stat_area;
|
MY_STAT stat_area;
|
||||||
char fname[FN_REFLEN+128];
|
char fname[FN_REFLEN+128];
|
||||||
const char *msg;
|
const char *msg;
|
||||||
fn_format(fname, master_info_fname, mysql_data_home, "", 4+32);
|
fn_format(fname, master_info_fname, mysql_data_home, "", 4+32);
|
||||||
|
|
||||||
// we need a mutex while we are changing master info parameters to
|
/*
|
||||||
// keep other threads from reading bogus info
|
We need a mutex while we are changing master info parameters to
|
||||||
|
keep other threads from reading bogus info
|
||||||
|
*/
|
||||||
|
|
||||||
pthread_mutex_lock(&mi->data_lock);
|
pthread_mutex_lock(&mi->data_lock);
|
||||||
fd = mi->fd;
|
fd = mi->fd;
|
||||||
@ -1121,8 +1124,7 @@ int init_master_info(MASTER_INFO* mi, const char* master_info_fname,
|
|||||||
if (init_strvar_from_file(mi->master_log_name,
|
if (init_strvar_from_file(mi->master_log_name,
|
||||||
sizeof(mi->master_log_name), &mi->file,
|
sizeof(mi->master_log_name), &mi->file,
|
||||||
(char*)"") ||
|
(char*)"") ||
|
||||||
init_intvar_from_file((int*)&mi->master_log_pos, &mi->file, 4)
|
init_intvar_from_file((int*)&mi->master_log_pos, &mi->file, 4) ||
|
||||||
||
|
|
||||||
init_strvar_from_file(mi->host, sizeof(mi->host), &mi->file,
|
init_strvar_from_file(mi->host, sizeof(mi->host), &mi->file,
|
||||||
master_host) ||
|
master_host) ||
|
||||||
init_strvar_from_file(mi->user, sizeof(mi->user), &mi->file,
|
init_strvar_from_file(mi->user, sizeof(mi->user), &mi->file,
|
||||||
@ -1131,8 +1133,7 @@ int init_master_info(MASTER_INFO* mi, const char* master_info_fname,
|
|||||||
master_password) ||
|
master_password) ||
|
||||||
init_intvar_from_file((int*)&mi->port, &mi->file, master_port) ||
|
init_intvar_from_file((int*)&mi->port, &mi->file, master_port) ||
|
||||||
init_intvar_from_file((int*)&mi->connect_retry, &mi->file,
|
init_intvar_from_file((int*)&mi->connect_retry, &mi->file,
|
||||||
master_connect_retry)
|
master_connect_retry))
|
||||||
)
|
|
||||||
{
|
{
|
||||||
msg="Error reading master configuration";
|
msg="Error reading master configuration";
|
||||||
goto err;
|
goto err;
|
||||||
@ -1140,8 +1141,7 @@ int init_master_info(MASTER_INFO* mi, const char* master_info_fname,
|
|||||||
}
|
}
|
||||||
|
|
||||||
mi->inited = 1;
|
mi->inited = 1;
|
||||||
// now change the cache from READ to WRITE - must do this
|
// now change cache READ -> WRITE - must do this before flush_master_info
|
||||||
// before flush_master_info
|
|
||||||
reinit_io_cache(&mi->file, WRITE_CACHE,0L,0,1);
|
reinit_io_cache(&mi->file, WRITE_CACHE,0L,0,1);
|
||||||
error=test(flush_master_info(mi));
|
error=test(flush_master_info(mi));
|
||||||
pthread_mutex_unlock(&mi->data_lock);
|
pthread_mutex_unlock(&mi->data_lock);
|
||||||
@ -1250,7 +1250,7 @@ int show_master_info(THD* thd, MASTER_INFO* mi)
|
|||||||
net_store_data(packet, (uint32)mi->rli.last_slave_errno);
|
net_store_data(packet, (uint32)mi->rli.last_slave_errno);
|
||||||
net_store_data(packet, mi->rli.last_slave_error);
|
net_store_data(packet, mi->rli.last_slave_error);
|
||||||
net_store_data(packet, mi->rli.slave_skip_counter);
|
net_store_data(packet, mi->rli.slave_skip_counter);
|
||||||
net_store_data(packet, (longlong)mi->rli.master_log_pos);
|
net_store_data(packet, (longlong) mi->rli.master_log_pos);
|
||||||
pthread_mutex_unlock(&mi->rli.data_lock);
|
pthread_mutex_unlock(&mi->rli.data_lock);
|
||||||
pthread_mutex_unlock(&mi->data_lock);
|
pthread_mutex_unlock(&mi->data_lock);
|
||||||
|
|
||||||
@ -1408,7 +1408,8 @@ static int request_dump(MYSQL* mysql, MASTER_INFO* mi)
|
|||||||
int len;
|
int len;
|
||||||
int binlog_flags = 0; // for now
|
int binlog_flags = 0; // for now
|
||||||
char* logname = mi->master_log_name;
|
char* logname = mi->master_log_name;
|
||||||
int4store(buf, mi->master_log_pos);
|
// TODO if big log files: Change next to int8store()
|
||||||
|
int4store(buf, (longlong) mi->master_log_pos);
|
||||||
int2store(buf + 4, binlog_flags);
|
int2store(buf + 4, binlog_flags);
|
||||||
int4store(buf + 6, server_id);
|
int4store(buf + 6, server_id);
|
||||||
len = (uint) strlen(logname);
|
len = (uint) strlen(logname);
|
||||||
@ -1521,7 +1522,6 @@ point. If you are sure that your master is ok, run this query manually on the\
|
|||||||
|
|
||||||
static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli)
|
static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli)
|
||||||
{
|
{
|
||||||
const char *error_msg;
|
|
||||||
DBUG_ASSERT(rli->sql_thd==thd);
|
DBUG_ASSERT(rli->sql_thd==thd);
|
||||||
Log_event * ev = next_event(rli);
|
Log_event * ev = next_event(rli);
|
||||||
DBUG_ASSERT(rli->sql_thd==thd);
|
DBUG_ASSERT(rli->sql_thd==thd);
|
||||||
@ -1582,7 +1582,7 @@ This may also be a network problem, or just a bug in the master or slave code.\
|
|||||||
pthread_handler_decl(handle_slave_io,arg)
|
pthread_handler_decl(handle_slave_io,arg)
|
||||||
{
|
{
|
||||||
#ifndef DBUG_OFF
|
#ifndef DBUG_OFF
|
||||||
slave_begin:
|
slave_begin:
|
||||||
#endif
|
#endif
|
||||||
THD *thd; // needs to be first for thread_stack
|
THD *thd; // needs to be first for thread_stack
|
||||||
MYSQL *mysql = NULL ;
|
MYSQL *mysql = NULL ;
|
||||||
@ -1649,14 +1649,14 @@ connected:
|
|||||||
thd->slave_net = &mysql->net;
|
thd->slave_net = &mysql->net;
|
||||||
thd->proc_info = "Checking master version";
|
thd->proc_info = "Checking master version";
|
||||||
if (check_master_version(mysql, mi))
|
if (check_master_version(mysql, mi))
|
||||||
{
|
|
||||||
goto err;
|
goto err;
|
||||||
}
|
|
||||||
if (!mi->old_format)
|
if (!mi->old_format)
|
||||||
{
|
{
|
||||||
// register ourselves with the master
|
/*
|
||||||
// if fails, this is not fatal - we just print the error message and go
|
Register ourselves with the master.
|
||||||
// on with life
|
If fails, this is not fatal - we just print the error message and go
|
||||||
|
on with life.
|
||||||
|
*/
|
||||||
thd->proc_info = "Registering slave on master";
|
thd->proc_info = "Registering slave on master";
|
||||||
if (register_slave_on_master(mysql) || update_slave_list(mysql))
|
if (register_slave_on_master(mysql) || update_slave_list(mysql))
|
||||||
goto err;
|
goto err;
|
||||||
@ -1677,9 +1677,11 @@ dump");
|
|||||||
|
|
||||||
thd->proc_info = "Waiiting to reconnect after a failed dump request";
|
thd->proc_info = "Waiiting to reconnect after a failed dump request";
|
||||||
mc_end_server(mysql);
|
mc_end_server(mysql);
|
||||||
// first time retry immediately, assuming that we can recover
|
/*
|
||||||
// right away - if first time fails, sleep between re-tries
|
First time retry immediately, assuming that we can recover
|
||||||
// hopefuly the admin can fix the problem sometime
|
right away - if first time fails, sleep between re-tries
|
||||||
|
hopefuly the admin can fix the problem sometime
|
||||||
|
*/
|
||||||
if (retried_once)
|
if (retried_once)
|
||||||
safe_sleep(thd, mi, mi->connect_retry);
|
safe_sleep(thd, mi, mi->connect_retry);
|
||||||
else
|
else
|
||||||
@ -1721,9 +1723,9 @@ after reconnect");
|
|||||||
if (mc_mysql_errno(mysql) == ER_NET_PACKET_TOO_LARGE)
|
if (mc_mysql_errno(mysql) == ER_NET_PACKET_TOO_LARGE)
|
||||||
{
|
{
|
||||||
sql_print_error("Log entry on master is longer than \
|
sql_print_error("Log entry on master is longer than \
|
||||||
max_allowed_packet on slave. Slave thread will be aborted. If the entry is \
|
max_allowed_packet (%ld) on slave. Slave thread will be aborted. If the entry \
|
||||||
really supposed to be that long, restart the server with a higher value of \
|
is correct, restart the server with a higher value of max_allowed_packet",
|
||||||
max_allowed_packet. The current value is %ld", max_allowed_packet);
|
max_allowed_packet);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1755,7 +1757,7 @@ reconnect done to recover from failed read");
|
|||||||
|
|
||||||
thd->proc_info = "Queueing event from master";
|
thd->proc_info = "Queueing event from master";
|
||||||
if (queue_event(mi,(const char*)mysql->net.read_pos + 1,
|
if (queue_event(mi,(const char*)mysql->net.read_pos + 1,
|
||||||
(uint)event_len))
|
event_len))
|
||||||
{
|
{
|
||||||
sql_print_error("Slave I/O thread could not queue event \
|
sql_print_error("Slave I/O thread could not queue event \
|
||||||
from master");
|
from master");
|
||||||
@ -1773,7 +1775,7 @@ from master");
|
|||||||
} // while(!slave_killed(thd,mi)) - slave loop
|
} // while(!slave_killed(thd,mi)) - slave loop
|
||||||
|
|
||||||
// error = 0;
|
// error = 0;
|
||||||
err:
|
err:
|
||||||
// print the current replication position
|
// print the current replication position
|
||||||
sql_print_error("Slave I/O thread exiting, read up to log '%s', position %s",
|
sql_print_error("Slave I/O thread exiting, read up to log '%s', position %s",
|
||||||
IO_RPL_LOG_NAME, llstr(mi->master_log_pos,llbuff));
|
IO_RPL_LOG_NAME, llstr(mi->master_log_pos,llbuff));
|
||||||
@ -1803,12 +1805,13 @@ from master");
|
|||||||
DBUG_RETURN(0); // Can't return anything here
|
DBUG_RETURN(0); // Can't return anything here
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* slave SQL logic thread */
|
/* slave SQL logic thread */
|
||||||
|
|
||||||
pthread_handler_decl(handle_slave_sql,arg)
|
pthread_handler_decl(handle_slave_sql,arg)
|
||||||
{
|
{
|
||||||
#ifndef DBUG_OFF
|
#ifndef DBUG_OFF
|
||||||
slave_begin:
|
slave_begin:
|
||||||
#endif
|
#endif
|
||||||
THD *thd; /* needs to be first for thread_stack */
|
THD *thd; /* needs to be first for thread_stack */
|
||||||
MYSQL *mysql = NULL ;
|
MYSQL *mysql = NULL ;
|
||||||
@ -1833,8 +1836,10 @@ pthread_handler_decl(handle_slave_sql,arg)
|
|||||||
pthread_detach_this_thread();
|
pthread_detach_this_thread();
|
||||||
if (init_slave_thread(thd, SLAVE_THD_SQL))
|
if (init_slave_thread(thd, SLAVE_THD_SQL))
|
||||||
{
|
{
|
||||||
// TODO: this is currently broken - slave start and change master
|
/*
|
||||||
// will be stuck if we fail here
|
TODO: this is currently broken - slave start and change master
|
||||||
|
will be stuck if we fail here
|
||||||
|
*/
|
||||||
pthread_cond_broadcast(&rli->start_cond);
|
pthread_cond_broadcast(&rli->start_cond);
|
||||||
pthread_mutex_unlock(&rli->run_lock);
|
pthread_mutex_unlock(&rli->run_lock);
|
||||||
sql_print_error("Failed during slave thread initialization");
|
sql_print_error("Failed during slave thread initialization");
|
||||||
@ -1876,7 +1881,7 @@ log '%s' at position %s,relay log: name='%s',pos='%s'", RPL_LOG_NAME,
|
|||||||
if (!slave_killed(thd,rli))
|
if (!slave_killed(thd,rli))
|
||||||
sql_print_error("\
|
sql_print_error("\
|
||||||
Error running query, slave SQL thread aborted. Fix the problem, and restart \
|
Error running query, slave SQL thread aborted. Fix the problem, and restart \
|
||||||
the slave SQL thread with \"mysqladmin start-slave\". We stopped at log \
|
the slave SQL thread with \"SLAVE START\". We stopped at log \
|
||||||
'%s' position %s",
|
'%s' position %s",
|
||||||
RPL_LOG_NAME, llstr(rli->master_log_pos, llbuff));
|
RPL_LOG_NAME, llstr(rli->master_log_pos, llbuff));
|
||||||
goto err;
|
goto err;
|
||||||
@ -1895,8 +1900,11 @@ the slave SQL thread with \"mysqladmin start-slave\". We stopped at log \
|
|||||||
DBUG_ASSERT(rli->slave_running == 1); // tracking buffer overrun
|
DBUG_ASSERT(rli->slave_running == 1); // tracking buffer overrun
|
||||||
rli->slave_running = 0;
|
rli->slave_running = 0;
|
||||||
rli->save_temporary_tables = thd->temporary_tables;
|
rli->save_temporary_tables = thd->temporary_tables;
|
||||||
//TODO: see if we can do this conditionally in next_event() instead
|
|
||||||
// to avoid unneeded position re-init
|
/*
|
||||||
|
TODO: see if we can do this conditionally in next_event() instead
|
||||||
|
to avoid unneeded position re-init
|
||||||
|
*/
|
||||||
rli->log_pos_current=0;
|
rli->log_pos_current=0;
|
||||||
thd->temporary_tables = 0; // remove tempation from destructor to close them
|
thd->temporary_tables = 0; // remove tempation from destructor to close them
|
||||||
DBUG_ASSERT(thd->net.buff != 0);
|
DBUG_ASSERT(thd->net.buff != 0);
|
||||||
@ -1918,6 +1926,7 @@ the slave SQL thread with \"mysqladmin start-slave\". We stopped at log \
|
|||||||
DBUG_RETURN(0); // Can't return anything here
|
DBUG_RETURN(0); // Can't return anything here
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// We assume we already locked mi->data_lock
|
// We assume we already locked mi->data_lock
|
||||||
static int process_io_rotate(MASTER_INFO* mi, Rotate_log_event* rev)
|
static int process_io_rotate(MASTER_INFO* mi, Rotate_log_event* rev)
|
||||||
{
|
{
|
||||||
@ -1929,9 +1938,9 @@ static int process_io_rotate(MASTER_INFO* mi, Rotate_log_event* rev)
|
|||||||
mi->master_log_name[rev->ident_len] = 0;
|
mi->master_log_name[rev->ident_len] = 0;
|
||||||
mi->master_log_pos = rev->pos;
|
mi->master_log_pos = rev->pos;
|
||||||
#ifndef DBUG_OFF
|
#ifndef DBUG_OFF
|
||||||
/* if we do not do this, we will be getting the first
|
/*
|
||||||
rotate event forever, so
|
If we do not do this, we will be getting the first
|
||||||
we need to not disconnect after one
|
rotate event forever, so we need to not disconnect after one.
|
||||||
*/
|
*/
|
||||||
if (disconnect_slave_event_count)
|
if (disconnect_slave_event_count)
|
||||||
events_till_disconnect++;
|
events_till_disconnect++;
|
||||||
@ -1939,18 +1948,21 @@ static int process_io_rotate(MASTER_INFO* mi, Rotate_log_event* rev)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: verify the issue with stop events, see if we need them at all
|
/*
|
||||||
// in the relay log
|
TODO: verify the issue with stop events, see if we need them at all
|
||||||
// TODO: test this code before release - it has to be tested on a separte
|
in the relay log
|
||||||
// setup with 3.23 master
|
TODO: test this code before release - it has to be tested on a separte
|
||||||
static int queue_old_event(MASTER_INFO* mi, const char* buf,
|
setup with 3.23 master
|
||||||
uint event_len)
|
*/
|
||||||
|
|
||||||
|
static int queue_old_event(MASTER_INFO *mi, const char *buf,
|
||||||
|
ulong event_len)
|
||||||
{
|
{
|
||||||
const char* errmsg = 0;
|
const char *errmsg = 0;
|
||||||
bool inc_pos = 1;
|
bool inc_pos = 1;
|
||||||
bool processed_stop_event = 0;
|
bool processed_stop_event = 0;
|
||||||
Log_event* ev = Log_event::read_log_event(buf,event_len, &errmsg,
|
Log_event *ev = Log_event::read_log_event(buf,event_len, &errmsg,
|
||||||
1/*old format*/);
|
1 /*old format*/ );
|
||||||
if (unlikely(!ev))
|
if (unlikely(!ev))
|
||||||
{
|
{
|
||||||
sql_print_error("Read invalid event from master: '%s',\
|
sql_print_error("Read invalid event from master: '%s',\
|
||||||
@ -1960,8 +1972,7 @@ static int queue_old_event(MASTER_INFO* mi, const char* buf,
|
|||||||
}
|
}
|
||||||
pthread_mutex_lock(&mi->data_lock);
|
pthread_mutex_lock(&mi->data_lock);
|
||||||
ev->log_pos = mi->master_log_pos;
|
ev->log_pos = mi->master_log_pos;
|
||||||
switch (ev->get_type_code())
|
switch (ev->get_type_code()) {
|
||||||
{
|
|
||||||
case ROTATE_EVENT:
|
case ROTATE_EVENT:
|
||||||
if (unlikely(process_io_rotate(mi,(Rotate_log_event*)ev)))
|
if (unlikely(process_io_rotate(mi,(Rotate_log_event*)ev)))
|
||||||
{
|
{
|
||||||
@ -2003,9 +2014,12 @@ static int queue_old_event(MASTER_INFO* mi, const char* buf,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: verify the issue with stop events, see if we need them at all
|
/*
|
||||||
// in the relay log
|
TODO: verify the issue with stop events, see if we need them at all
|
||||||
int queue_event(MASTER_INFO* mi,const char* buf,uint event_len)
|
in the relay log
|
||||||
|
*/
|
||||||
|
|
||||||
|
int queue_event(MASTER_INFO* mi,const char* buf, ulong event_len)
|
||||||
{
|
{
|
||||||
int error=0;
|
int error=0;
|
||||||
bool inc_pos = 1;
|
bool inc_pos = 1;
|
||||||
@ -2015,10 +2029,11 @@ int queue_event(MASTER_INFO* mi,const char* buf,uint event_len)
|
|||||||
|
|
||||||
pthread_mutex_lock(&mi->data_lock);
|
pthread_mutex_lock(&mi->data_lock);
|
||||||
|
|
||||||
// TODO: figure out if other events in addition to Rotate
|
/*
|
||||||
// require special processing
|
TODO: figure out if other events in addition to Rotate
|
||||||
switch (buf[EVENT_TYPE_OFFSET])
|
require special processing
|
||||||
{
|
*/
|
||||||
|
switch (buf[EVENT_TYPE_OFFSET]) {
|
||||||
case STOP_EVENT:
|
case STOP_EVENT:
|
||||||
processed_stop_event=1;
|
processed_stop_event=1;
|
||||||
break;
|
break;
|
||||||
@ -2048,6 +2063,7 @@ int queue_event(MASTER_INFO* mi,const char* buf,uint event_len)
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void end_relay_log_info(RELAY_LOG_INFO* rli)
|
void end_relay_log_info(RELAY_LOG_INFO* rli)
|
||||||
{
|
{
|
||||||
if (!rli->inited)
|
if (!rli->inited)
|
||||||
@ -2075,10 +2091,12 @@ static int safe_connect(THD* thd, MYSQL* mysql, MASTER_INFO* mi)
|
|||||||
return connect_to_master(thd, mysql, mi, 0);
|
return connect_to_master(thd, mysql, mi, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Try to connect until successful or slave killed or we have retried
|
Try to connect until successful or slave killed or we have retried
|
||||||
master_retry_count times
|
master_retry_count times
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int connect_to_master(THD* thd, MYSQL* mysql, MASTER_INFO* mi,
|
static int connect_to_master(THD* thd, MYSQL* mysql, MASTER_INFO* mi,
|
||||||
bool reconnect)
|
bool reconnect)
|
||||||
{
|
{
|
||||||
@ -2091,7 +2109,7 @@ static int connect_to_master(THD* thd, MYSQL* mysql, MASTER_INFO* mi,
|
|||||||
events_till_disconnect = disconnect_slave_event_count;
|
events_till_disconnect = disconnect_slave_event_count;
|
||||||
#endif
|
#endif
|
||||||
while (!(slave_was_killed = slave_killed(thd,mi)) &&
|
while (!(slave_was_killed = slave_killed(thd,mi)) &&
|
||||||
(reconnect ? mc_mysql_reconnect(mysql) :
|
(reconnect ? mc_mysql_reconnect(mysql) != 0 :
|
||||||
!mc_mysql_connect(mysql, mi->host, mi->user, mi->password, 0,
|
!mc_mysql_connect(mysql, mi->host, mi->user, mi->password, 0,
|
||||||
mi->port, 0, 0)))
|
mi->port, 0, 0)))
|
||||||
{
|
{
|
||||||
@ -2105,7 +2123,8 @@ static int connect_to_master(THD* thd, MYSQL* mysql, MASTER_INFO* mi,
|
|||||||
mi->connect_retry);
|
mi->connect_retry);
|
||||||
}
|
}
|
||||||
safe_sleep(thd,mi,mi->connect_retry);
|
safe_sleep(thd,mi,mi->connect_retry);
|
||||||
/* by default we try forever. The reason is that failure will trigger
|
/*
|
||||||
|
By default we try forever. The reason is that failure will trigger
|
||||||
master election, so if the user did not set master_retry_count we
|
master election, so if the user did not set master_retry_count we
|
||||||
do not want to have electioin triggered on the first failure to
|
do not want to have electioin triggered on the first failure to
|
||||||
connect
|
connect
|
||||||
@ -2141,6 +2160,7 @@ replication resumed in log '%s' at position %s", mi->user,
|
|||||||
return slave_was_killed;
|
return slave_was_killed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Try to connect until successful or slave killed or we have retried
|
Try to connect until successful or slave killed or we have retried
|
||||||
master_retry_count times
|
master_retry_count times
|
||||||
@ -2172,7 +2192,7 @@ IO_CACHE* reopen_relay_log(RELAY_LOG_INFO* rli, const char** errmsg)
|
|||||||
IO_CACHE* cur_log = rli->cur_log=&rli->cache_buf;
|
IO_CACHE* cur_log = rli->cur_log=&rli->cache_buf;
|
||||||
DBUG_ASSERT(rli->cur_log_fd == -1);
|
DBUG_ASSERT(rli->cur_log_fd == -1);
|
||||||
if ((rli->cur_log_fd=open_binlog(cur_log,rli->relay_log_name,
|
if ((rli->cur_log_fd=open_binlog(cur_log,rli->relay_log_name,
|
||||||
errmsg))<0)
|
errmsg)) <0)
|
||||||
return 0;
|
return 0;
|
||||||
my_b_seek(cur_log,rli->relay_log_pos);
|
my_b_seek(cur_log,rli->relay_log_pos);
|
||||||
return cur_log;
|
return cur_log;
|
||||||
@ -2188,29 +2208,36 @@ Log_event* next_event(RELAY_LOG_INFO* rli)
|
|||||||
bool was_killed;
|
bool was_killed;
|
||||||
DBUG_ASSERT(thd != 0);
|
DBUG_ASSERT(thd != 0);
|
||||||
|
|
||||||
// For most operations we need to protect rli members with data_lock,
|
/*
|
||||||
// so we will hold it for the most of the loop below
|
For most operations we need to protect rli members with data_lock,
|
||||||
// However, we will release it whenever it is worth the hassle,
|
so we will hold it for the most of the loop below
|
||||||
// and in the cases when we go into a pthread_cond_wait() with the
|
However, we will release it whenever it is worth the hassle,
|
||||||
// non-data_lock mutex
|
and in the cases when we go into a pthread_cond_wait() with the
|
||||||
|
non-data_lock mutex
|
||||||
|
*/
|
||||||
pthread_mutex_lock(&rli->data_lock);
|
pthread_mutex_lock(&rli->data_lock);
|
||||||
|
|
||||||
for (;!(was_killed=slave_killed(thd,rli));)
|
for (; !(was_killed=slave_killed(thd,rli)) ;)
|
||||||
{
|
{
|
||||||
// we can have two kinds of log reading:
|
/*
|
||||||
// hot_log - rli->cur_log points at the IO_CACHE of relay_log, which
|
We can have two kinds of log reading:
|
||||||
// is actively being updated by the I/O thread. We need to be careful
|
hot_log - rli->cur_log points at the IO_CACHE of relay_log, which
|
||||||
// in this case and make sure that we are not looking at a stale log that
|
is actively being updated by the I/O thread. We need to be careful
|
||||||
// has already been rotated. If it has been, we reopen the log
|
in this case and make sure that we are not looking at a stale log that
|
||||||
// the other case is much simpler - we just have a read only log that
|
has already been rotated. If it has been, we reopen the log
|
||||||
// nobody else will be updating.
|
the other case is much simpler - we just have a read only log that
|
||||||
|
nobody else will be updating.
|
||||||
|
*/
|
||||||
bool hot_log;
|
bool hot_log;
|
||||||
if ((hot_log = (cur_log != &rli->cache_buf)))
|
if ((hot_log = (cur_log != &rli->cache_buf)))
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(rli->cur_log_fd == -1); // foreign descriptor
|
DBUG_ASSERT(rli->cur_log_fd == -1); // foreign descriptor
|
||||||
pthread_mutex_lock(log_lock);
|
pthread_mutex_lock(log_lock);
|
||||||
// reading cur_log->init_count here is safe because the log will only
|
|
||||||
// be rotated when we hold relay_log.LOCK_log
|
/*
|
||||||
|
Reading cur_log->init_count here is safe because the log will only
|
||||||
|
be rotated when we hold relay_log.LOCK_log
|
||||||
|
*/
|
||||||
if (cur_log->init_count != rli->cur_log_init_count)
|
if (cur_log->init_count != rli->cur_log_init_count)
|
||||||
{
|
{
|
||||||
if (!(cur_log=reopen_relay_log(rli,&errmsg)))
|
if (!(cur_log=reopen_relay_log(rli,&errmsg)))
|
||||||
@ -2235,29 +2262,37 @@ Log_event* next_event(RELAY_LOG_INFO* rli)
|
|||||||
DBUG_ASSERT(thd==rli->sql_thd);
|
DBUG_ASSERT(thd==rli->sql_thd);
|
||||||
if (!cur_log->error) /* EOF */
|
if (!cur_log->error) /* EOF */
|
||||||
{
|
{
|
||||||
// on a hot log, EOF means that there are no more updates to
|
/*
|
||||||
// process and we must block until I/O thread adds some and
|
On a hot log, EOF means that there are no more updates to
|
||||||
// signals us to continue
|
process and we must block until I/O thread adds some and
|
||||||
|
signals us to continue
|
||||||
|
*/
|
||||||
if (hot_log)
|
if (hot_log)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(cur_log->init_count == rli->cur_log_init_count);
|
DBUG_ASSERT(cur_log->init_count == rli->cur_log_init_count);
|
||||||
//we can, and should release data_lock while we are waiting for
|
/*
|
||||||
// update. If we do not, show slave status will block
|
We can, and should release data_lock while we are waiting for
|
||||||
|
update. If we do not, show slave status will block
|
||||||
|
*/
|
||||||
pthread_mutex_unlock(&rli->data_lock);
|
pthread_mutex_unlock(&rli->data_lock);
|
||||||
|
|
||||||
// IMPORTANT: note that wait_for_update will unlock LOCK_log, but
|
/*
|
||||||
// expects the caller to lock it
|
IMPORTANT: note that wait_for_update will unlock LOCK_log, but
|
||||||
|
expects the caller to lock it
|
||||||
|
*/
|
||||||
rli->relay_log.wait_for_update(rli->sql_thd);
|
rli->relay_log.wait_for_update(rli->sql_thd);
|
||||||
|
|
||||||
// re-acquire data lock since we released it earlier
|
// re-acquire data lock since we released it earlier
|
||||||
pthread_mutex_lock(&rli->data_lock);
|
pthread_mutex_lock(&rli->data_lock);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// if the log was not hot, we need to move to the next log in
|
|
||||||
// sequence. The next log could be hot or cold, we deal with both
|
|
||||||
// cases separately after doing some common initialization
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
If the log was not hot, we need to move to the next log in
|
||||||
|
sequence. The next log could be hot or cold, we deal with both
|
||||||
|
cases separately after doing some common initialization
|
||||||
|
*/
|
||||||
end_io_cache(cur_log);
|
end_io_cache(cur_log);
|
||||||
DBUG_ASSERT(rli->cur_log_fd >= 0);
|
DBUG_ASSERT(rli->cur_log_fd >= 0);
|
||||||
my_close(rli->cur_log_fd, MYF(MY_WME));
|
my_close(rli->cur_log_fd, MYF(MY_WME));
|
||||||
@ -2282,21 +2317,25 @@ Log_event* next_event(RELAY_LOG_INFO* rli)
|
|||||||
rli->cur_log_init_count = cur_log->init_count;
|
rli->cur_log_init_count = cur_log->init_count;
|
||||||
DBUG_ASSERT(rli->cur_log_fd == -1);
|
DBUG_ASSERT(rli->cur_log_fd == -1);
|
||||||
|
|
||||||
// read pointer has to be at the start since we are the only
|
/*
|
||||||
// reader
|
Read pointer has to be at the start since we are the only
|
||||||
|
reader
|
||||||
|
*/
|
||||||
if (check_binlog_magic(cur_log,&errmsg))
|
if (check_binlog_magic(cur_log,&errmsg))
|
||||||
goto err;
|
goto err;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// if we get here, the log was not hot, so we will have to
|
/*
|
||||||
// open it ourselves
|
if we get here, the log was not hot, so we will have to
|
||||||
|
open it ourselves
|
||||||
|
*/
|
||||||
#ifdef EXTRA_DEBUG
|
#ifdef EXTRA_DEBUG
|
||||||
sql_print_error("next log '%s' is not active",
|
sql_print_error("next log '%s' is not active",
|
||||||
rli->linfo.log_file_name);
|
rli->linfo.log_file_name);
|
||||||
#endif
|
#endif
|
||||||
// open_binlog() will check the magic header
|
// open_binlog() will check the magic header
|
||||||
if ((rli->cur_log_fd=open_binlog(cur_log,rli->linfo.log_file_name,
|
if ((rli->cur_log_fd=open_binlog(cur_log,rli->linfo.log_file_name,
|
||||||
&errmsg))<0)
|
&errmsg)) <0)
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
181
sql/slave.h
181
sql/slave.h
@ -33,8 +33,11 @@ extern my_string opt_relay_logname, opt_relaylog_index_name;
|
|||||||
extern bool opt_skip_slave_start;
|
extern bool opt_skip_slave_start;
|
||||||
struct st_master_info;
|
struct st_master_info;
|
||||||
|
|
||||||
// TODO: this needs to be redone, but for now it does not matter since
|
/*
|
||||||
// we do not have multi-master yet.
|
TODO: this needs to be redone, but for now it does not matter since
|
||||||
|
we do not have multi-master yet.
|
||||||
|
*/
|
||||||
|
|
||||||
#define LOCK_ACTIVE_MI { pthread_mutex_lock(&LOCK_active_mi); \
|
#define LOCK_ACTIVE_MI { pthread_mutex_lock(&LOCK_active_mi); \
|
||||||
++active_mi_in_use; \
|
++active_mi_in_use; \
|
||||||
pthread_mutex_unlock(&LOCK_active_mi);}
|
pthread_mutex_unlock(&LOCK_active_mi);}
|
||||||
@ -62,56 +65,33 @@ struct st_master_info;
|
|||||||
|
|
||||||
To clean up, call end_relay_log_info()
|
To clean up, call end_relay_log_info()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef struct st_relay_log_info
|
typedef struct st_relay_log_info
|
||||||
{
|
{
|
||||||
// info_fd - file descriptor of the info file. set only during
|
/*** The following variables can only be read when protect by data lock ****/
|
||||||
// initialization or clean up - safe to read anytime
|
/*
|
||||||
// cur_log_fd - file descriptor of the current read relay log, protected by
|
info_fd - file descriptor of the info file. set only during
|
||||||
// data_lock
|
initialization or clean up - safe to read anytime
|
||||||
|
cur_log_fd - file descriptor of the current read relay log
|
||||||
|
*/
|
||||||
File info_fd,cur_log_fd;
|
File info_fd,cur_log_fd;
|
||||||
|
// name of current read relay log
|
||||||
// IO_CACHE of the info file - set only during init or end, safe to read
|
|
||||||
// anytime
|
|
||||||
IO_CACHE info_file;
|
|
||||||
|
|
||||||
// name of current read relay log - protected by data_lock
|
|
||||||
char relay_log_name[FN_REFLEN];
|
char relay_log_name[FN_REFLEN];
|
||||||
|
// master log name corresponding to current read position
|
||||||
// master log name corresponding to current read position - protected by
|
|
||||||
// data lock
|
|
||||||
char master_log_name[FN_REFLEN];
|
char master_log_name[FN_REFLEN];
|
||||||
|
// original log position of last processed event
|
||||||
|
volatile my_off_t master_log_pos;
|
||||||
|
|
||||||
// original log position of last processed event - protected by data_lock
|
/*
|
||||||
volatile uint32 master_log_pos;
|
current offset in the relay log.
|
||||||
|
pending - in some cases we do not increment offset immediately after
|
||||||
// when we restart slave thread we need to have access to the previously
|
processing an event, because the following event needs to be processed
|
||||||
// created temporary tables. Modified only on init/end and by the SQL
|
atomically together with this one ( so far, there is only one type of
|
||||||
// thread, read only by SQL thread, need no mutex
|
such event - Intvar_event that sets auto_increment value). However, once
|
||||||
TABLE* save_temporary_tables;
|
both events have been processed, we need to increment by the cumulative
|
||||||
|
offset. pending stored the extra offset to be added to the position.
|
||||||
// relay_log_pos - current offset in the relay log - protected by data_lock
|
*/
|
||||||
// pending - in some cases we do not increment offset immediately after
|
ulonglong relay_log_pos, pending;
|
||||||
// processing an event, because the following event needs to be processed
|
|
||||||
// atomically together with this one ( so far, there is only one type of
|
|
||||||
// such event - Intvar_event that sets auto_increment value). However, once
|
|
||||||
// both events have been processed, we need to increment by the cumulative
|
|
||||||
// offset. pending stored the extra offset to be added to the position.
|
|
||||||
ulonglong relay_log_pos,pending;
|
|
||||||
|
|
||||||
// standard lock acquistion order to avoid deadlocks:
|
|
||||||
// run_lock, data_lock, relay_log.LOCK_log,relay_log.LOCK_index
|
|
||||||
pthread_mutex_t data_lock,run_lock;
|
|
||||||
|
|
||||||
// start_cond is broadcast when SQL thread is started
|
|
||||||
// stop_cond - when stopped
|
|
||||||
// data_cond - when data protected by data_lock changes
|
|
||||||
pthread_cond_t start_cond,stop_cond,data_cond;
|
|
||||||
|
|
||||||
// if not set, the value of other members of the structure are undefined
|
|
||||||
bool inited;
|
|
||||||
|
|
||||||
// parent master info structure
|
|
||||||
struct st_master_info *mi;
|
|
||||||
|
|
||||||
// protected with internal locks
|
// protected with internal locks
|
||||||
// must get data_lock when resetting the logs
|
// must get data_lock when resetting the logs
|
||||||
@ -119,15 +99,50 @@ typedef struct st_relay_log_info
|
|||||||
LOG_INFO linfo;
|
LOG_INFO linfo;
|
||||||
IO_CACHE cache_buf,*cur_log;
|
IO_CACHE cache_buf,*cur_log;
|
||||||
|
|
||||||
/* needed to deal properly with cur_log getting closed and re-opened with
|
/*** The following variables are safe to read any time ***/
|
||||||
|
|
||||||
|
// IO_CACHE of the info file - set only during init or end
|
||||||
|
IO_CACHE info_file;
|
||||||
|
|
||||||
|
/*
|
||||||
|
When we restart slave thread we need to have access to the previously
|
||||||
|
created temporary tables. Modified only on init/end and by the SQL
|
||||||
|
thread, read only by SQL thread.
|
||||||
|
*/
|
||||||
|
TABLE* save_temporary_tables;
|
||||||
|
|
||||||
|
/*
|
||||||
|
standard lock acquistion order to avoid deadlocks:
|
||||||
|
run_lock, data_lock, relay_log.LOCK_log, relay_log.LOCK_index
|
||||||
|
*/
|
||||||
|
pthread_mutex_t data_lock,run_lock;
|
||||||
|
|
||||||
|
/*
|
||||||
|
start_cond is broadcast when SQL thread is started
|
||||||
|
stop_cond - when stopped
|
||||||
|
data_cond - when data protected by data_lock changes
|
||||||
|
*/
|
||||||
|
pthread_cond_t start_cond, stop_cond, data_cond;
|
||||||
|
|
||||||
|
// if not set, the value of other members of the structure are undefined
|
||||||
|
bool inited;
|
||||||
|
|
||||||
|
// parent master info structure
|
||||||
|
struct st_master_info *mi;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Needed to deal properly with cur_log getting closed and re-opened with
|
||||||
a different log under our feet
|
a different log under our feet
|
||||||
*/
|
*/
|
||||||
int cur_log_init_count;
|
int cur_log_init_count;
|
||||||
|
|
||||||
volatile bool abort_slave, slave_running;
|
volatile bool abort_slave, slave_running;
|
||||||
// needed for problems when slave stops and
|
|
||||||
// we want to restart it skipping one or more events in the master log that
|
/*
|
||||||
// have caused errors, and have been manually applied by DBA already
|
Needed for problems when slave stops and we want to restart it
|
||||||
|
skipping one or more events in the master log that have caused
|
||||||
|
errors, and have been manually applied by DBA already.
|
||||||
|
*/
|
||||||
volatile uint32 slave_skip_counter;
|
volatile uint32 slave_skip_counter;
|
||||||
#ifndef DBUG_OFF
|
#ifndef DBUG_OFF
|
||||||
int events_till_abort;
|
int events_till_abort;
|
||||||
@ -168,13 +183,15 @@ typedef struct st_relay_log_info
|
|||||||
relay_log_pos += val+pending;
|
relay_log_pos += val+pending;
|
||||||
pending = 0;
|
pending = 0;
|
||||||
if (log_pos)
|
if (log_pos)
|
||||||
master_log_pos = log_pos+val;
|
master_log_pos = log_pos+ val;
|
||||||
pthread_cond_broadcast(&data_cond);
|
pthread_cond_broadcast(&data_cond);
|
||||||
if (!skip_lock)
|
if (!skip_lock)
|
||||||
pthread_mutex_unlock(&data_lock);
|
pthread_mutex_unlock(&data_lock);
|
||||||
}
|
}
|
||||||
// thread safe read of position - not needed if we are in the slave thread,
|
/*
|
||||||
// but required otherwise
|
thread safe read of position - not needed if we are in the slave thread,
|
||||||
|
but required otherwise
|
||||||
|
*/
|
||||||
inline void read_pos(ulonglong& var)
|
inline void read_pos(ulonglong& var)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&data_lock);
|
pthread_mutex_lock(&data_lock);
|
||||||
@ -185,12 +202,17 @@ typedef struct st_relay_log_info
|
|||||||
int wait_for_pos(THD* thd, String* log_name, ulonglong log_pos);
|
int wait_for_pos(THD* thd, String* log_name, ulonglong log_pos);
|
||||||
} RELAY_LOG_INFO;
|
} RELAY_LOG_INFO;
|
||||||
|
|
||||||
// repopen_relay_log() is called when we notice that the current "hot" log
|
/*
|
||||||
// got rotated under our feet
|
repopen_relay_log() is called when we notice that the current "hot" log
|
||||||
|
got rotated under our feet
|
||||||
|
*/
|
||||||
|
|
||||||
IO_CACHE* reopen_relay_log(RELAY_LOG_INFO* rli, const char** errmsg);
|
IO_CACHE* reopen_relay_log(RELAY_LOG_INFO* rli, const char** errmsg);
|
||||||
Log_event* next_event(RELAY_LOG_INFO* rli);
|
Log_event* next_event(RELAY_LOG_INFO* rli);
|
||||||
|
|
||||||
/* st_master_info contains information about how to connect to a master,
|
|
||||||
|
/*
|
||||||
|
st_master_info contains information about how to connect to a master,
|
||||||
current master log name, and current log offset, as well as misc
|
current master log name, and current log offset, as well as misc
|
||||||
control variables
|
control variables
|
||||||
|
|
||||||
@ -214,14 +236,14 @@ Log_event* next_event(RELAY_LOG_INFO* rli);
|
|||||||
flush_master_info() is required.
|
flush_master_info() is required.
|
||||||
|
|
||||||
To clean up, call end_master_info()
|
To clean up, call end_master_info()
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
typedef struct st_master_info
|
typedef struct st_master_info
|
||||||
{
|
{
|
||||||
char master_log_name[FN_REFLEN];
|
char master_log_name[FN_REFLEN];
|
||||||
|
|
||||||
ulonglong master_log_pos;
|
my_off_t master_log_pos;
|
||||||
File fd;
|
File fd;
|
||||||
IO_CACHE file;
|
IO_CACHE file;
|
||||||
|
|
||||||
@ -229,24 +251,22 @@ typedef struct st_master_info
|
|||||||
char host[HOSTNAME_LENGTH+1];
|
char host[HOSTNAME_LENGTH+1];
|
||||||
char user[USERNAME_LENGTH+1];
|
char user[USERNAME_LENGTH+1];
|
||||||
char password[HASH_PASSWORD_LENGTH+1];
|
char password[HASH_PASSWORD_LENGTH+1];
|
||||||
uint port;
|
|
||||||
uint connect_retry;
|
|
||||||
pthread_mutex_t data_lock,run_lock;
|
pthread_mutex_t data_lock,run_lock;
|
||||||
pthread_cond_t data_cond,start_cond,stop_cond;
|
pthread_cond_t data_cond,start_cond,stop_cond;
|
||||||
bool inited;
|
THD *io_thd;
|
||||||
bool old_format; /* master binlog is in 3.23 format */
|
|
||||||
RELAY_LOG_INFO rli;
|
RELAY_LOG_INFO rli;
|
||||||
|
uint port;
|
||||||
|
uint connect_retry;
|
||||||
#ifndef DBUG_OFF
|
#ifndef DBUG_OFF
|
||||||
int events_till_abort;
|
int events_till_abort;
|
||||||
#endif
|
#endif
|
||||||
|
bool inited;
|
||||||
|
bool old_format; // master binlog is in 3.23 format
|
||||||
volatile bool abort_slave, slave_running;
|
volatile bool abort_slave, slave_running;
|
||||||
|
|
||||||
bool ignore_stop_event;
|
bool ignore_stop_event;
|
||||||
|
|
||||||
THD* io_thd;
|
|
||||||
|
|
||||||
st_master_info():fd(-1),inited(0),
|
st_master_info():fd(-1), io_thd(0), inited(0), old_format(0)
|
||||||
old_format(0),io_thd(0)
|
|
||||||
{
|
{
|
||||||
host[0] = 0; user[0] = 0; password[0] = 0;
|
host[0] = 0; user[0] = 0; password[0] = 0;
|
||||||
pthread_mutex_init(&run_lock, MY_MUTEX_INIT_FAST);
|
pthread_mutex_init(&run_lock, MY_MUTEX_INIT_FAST);
|
||||||
@ -267,7 +287,7 @@ typedef struct st_master_info
|
|||||||
|
|
||||||
} MASTER_INFO;
|
} MASTER_INFO;
|
||||||
|
|
||||||
int queue_event(MASTER_INFO* mi,const char* buf,uint event_len);
|
int queue_event(MASTER_INFO* mi,const char* buf,ulong event_len);
|
||||||
|
|
||||||
typedef struct st_table_rule_ent
|
typedef struct st_table_rule_ent
|
||||||
{
|
{
|
||||||
@ -288,10 +308,12 @@ typedef struct st_table_rule_ent
|
|||||||
/* masks for start/stop operations on io and sql slave threads */
|
/* masks for start/stop operations on io and sql slave threads */
|
||||||
#define SLAVE_IO 1
|
#define SLAVE_IO 1
|
||||||
#define SLAVE_SQL 2
|
#define SLAVE_SQL 2
|
||||||
#define SLAVE_FORCE_ALL 4 /* if this is set, if first gives an
|
|
||||||
error, second will be tried. Otherwise,
|
/*
|
||||||
if first fails, we fail
|
If the following is set, if first gives an error, second will be
|
||||||
*/
|
tried. Otherwise, if first fails, we fail.
|
||||||
|
*/
|
||||||
|
#define SLAVE_FORCE_ALL 4
|
||||||
|
|
||||||
int init_slave();
|
int init_slave();
|
||||||
void init_slave_skip_errors(char* arg);
|
void init_slave_skip_errors(char* arg);
|
||||||
@ -307,7 +329,8 @@ int terminate_slave_thread(THD* thd, pthread_mutex_t* term_mutex,
|
|||||||
int start_slave_threads(bool need_slave_mutex, bool wait_for_start,
|
int start_slave_threads(bool need_slave_mutex, bool wait_for_start,
|
||||||
MASTER_INFO* mi, const char* master_info_fname,
|
MASTER_INFO* mi, const char* master_info_fname,
|
||||||
const char* slave_info_fname, int thread_mask);
|
const char* slave_info_fname, int thread_mask);
|
||||||
/* cond_lock is usually same as start_lock. It is needed for the case when
|
/*
|
||||||
|
cond_lock is usually same as start_lock. It is needed for the case when
|
||||||
start_lock is 0 which happens if start_slave_thread() is called already
|
start_lock is 0 which happens if start_slave_thread() is called already
|
||||||
inside the start_lock section, but at the same time we want a
|
inside the start_lock section, but at the same time we want a
|
||||||
pthread_cond_wait() on start_cond,start_lock
|
pthread_cond_wait() on start_cond,start_lock
|
||||||
@ -318,24 +341,26 @@ int start_slave_thread(pthread_handler h_func, pthread_mutex_t* start_lock,
|
|||||||
volatile bool* slave_running,
|
volatile bool* slave_running,
|
||||||
MASTER_INFO* mi);
|
MASTER_INFO* mi);
|
||||||
|
|
||||||
|
// If fd is -1, dump to NET
|
||||||
int mysql_table_dump(THD* thd, const char* db,
|
int mysql_table_dump(THD* thd, const char* db,
|
||||||
const char* tbl_name, int fd = -1);
|
const char* tbl_name, int fd = -1);
|
||||||
// if fd is -1, dump to NET
|
|
||||||
|
|
||||||
|
// retrieve non-exitent table from master
|
||||||
int fetch_master_table(THD* thd, const char* db_name, const char* table_name,
|
int fetch_master_table(THD* thd, const char* db_name, const char* table_name,
|
||||||
MASTER_INFO* mi, MYSQL* mysql);
|
MASTER_INFO* mi, MYSQL* mysql);
|
||||||
// retrieve non-exitent table from master
|
|
||||||
|
|
||||||
int show_master_info(THD* thd, MASTER_INFO* mi);
|
int show_master_info(THD* thd, MASTER_INFO* mi);
|
||||||
int show_binlog_info(THD* thd);
|
int show_binlog_info(THD* thd);
|
||||||
|
|
||||||
|
// See if the query uses any tables that should not be replicated
|
||||||
int tables_ok(THD* thd, TABLE_LIST* tables);
|
int tables_ok(THD* thd, TABLE_LIST* tables);
|
||||||
// see if the query uses any tables that should not be replicated
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Check to see if the database is ok to operate on with respect to the
|
||||||
|
do and ignore lists - used in replication
|
||||||
|
*/
|
||||||
int db_ok(const char* db, I_List<i_string> &do_list,
|
int db_ok(const char* db, I_List<i_string> &do_list,
|
||||||
I_List<i_string> &ignore_list );
|
I_List<i_string> &ignore_list );
|
||||||
// check to see if the database is ok to operate on with respect to the
|
|
||||||
// do and ignore lists - used in replication
|
|
||||||
|
|
||||||
int add_table_rule(HASH* h, const char* table_spec);
|
int add_table_rule(HASH* h, const char* table_spec);
|
||||||
int add_wild_table_rule(DYNAMIC_ARRAY* a, const char* table_spec);
|
int add_wild_table_rule(DYNAMIC_ARRAY* a, const char* table_spec);
|
||||||
@ -388,5 +413,3 @@ extern I_List<i_string_pair> replicate_rewrite_db;
|
|||||||
extern I_List<THD> threads;
|
extern I_List<THD> threads;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
|
/* Copyright (C) 2000 MySQL AB
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -243,13 +243,16 @@ int acl_init(bool dont_read_acl_tables)
|
|||||||
user.hostname_length=user.host.hostname ? (uint) strlen(user.host.hostname) : 0;
|
user.hostname_length=user.host.hostname ? (uint) strlen(user.host.hostname) : 0;
|
||||||
if (table->fields >=23)
|
if (table->fields >=23)
|
||||||
{
|
{
|
||||||
|
/* Table has new MySQL usage limits */
|
||||||
char *ptr = get_field(&mem, table, 21);
|
char *ptr = get_field(&mem, table, 21);
|
||||||
user.questions=atoi(ptr);
|
user.questions=atoi(ptr);
|
||||||
ptr = get_field(&mem, table, 22);
|
ptr = get_field(&mem, table, 22);
|
||||||
user.updates=atoi(ptr);
|
user.updates=atoi(ptr);
|
||||||
if (user.questions)
|
if (user.questions)
|
||||||
mqh_used=true;
|
mqh_used=1;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
user.questions=user.updates=0;
|
||||||
#ifndef TO_BE_REMOVED
|
#ifndef TO_BE_REMOVED
|
||||||
if (table->fields <= 13)
|
if (table->fields <= 13)
|
||||||
{ // Without grant
|
{ // Without grant
|
||||||
@ -430,15 +433,20 @@ static int acl_compare(ACL_ACCESS *a,ACL_ACCESS *b)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Get master privilges for user (priviliges for all tables). Required to connect */
|
/*
|
||||||
|
Get master privilges for user (priviliges for all tables).
|
||||||
|
Required before connecting to MySQL
|
||||||
|
*/
|
||||||
|
|
||||||
uint acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
|
uint acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
|
||||||
const char *password,const char *message,char **priv_user,
|
const char *password,const char *message,char **priv_user,
|
||||||
bool old_ver, uint *max)
|
bool old_ver, uint *max_questions)
|
||||||
{
|
{
|
||||||
uint user_access=NO_ACCESS;
|
uint user_access=NO_ACCESS;
|
||||||
*priv_user=(char*) user;
|
*priv_user=(char*) user;
|
||||||
char *ptr=0;
|
char *ptr=0;
|
||||||
|
|
||||||
|
*max_questions=0;
|
||||||
if (!initialized)
|
if (!initialized)
|
||||||
return (uint) ~NO_ACCESS; // If no data allow anything /* purecov: tested */
|
return (uint) ~NO_ACCESS; // If no data allow anything /* purecov: tested */
|
||||||
VOID(pthread_mutex_lock(&acl_cache->lock));
|
VOID(pthread_mutex_lock(&acl_cache->lock));
|
||||||
@ -546,7 +554,7 @@ uint acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
|
|||||||
#else /* HAVE_OPENSSL */
|
#else /* HAVE_OPENSSL */
|
||||||
user_access=acl_user->access;
|
user_access=acl_user->access;
|
||||||
#endif /* HAVE_OPENSSL */
|
#endif /* HAVE_OPENSSL */
|
||||||
*max=acl_user->questions;
|
*max_questions=acl_user->questions;
|
||||||
if (!acl_user->user)
|
if (!acl_user->user)
|
||||||
*priv_user=(char*) ""; // Change to anonymous user /* purecov: inspected */
|
*priv_user=(char*) ""; // Change to anonymous user /* purecov: inspected */
|
||||||
break;
|
break;
|
||||||
@ -1221,12 +1229,10 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* HAVE_OPENSSL */
|
#endif /* HAVE_OPENSSL */
|
||||||
if (table->fields>=23 && thd->lex.mqh)
|
if (table->fields >= 23 && thd->lex.mqh)
|
||||||
{
|
{
|
||||||
char buff[33];
|
table->field[21]->store((longlong) thd->lex.mqh);
|
||||||
int len =int2str((long)thd->lex.mqh,buff,10) - buff;
|
mqh_used=1;
|
||||||
table->field[21]->store(buff,len);
|
|
||||||
mqh_used=true;
|
|
||||||
}
|
}
|
||||||
if (old_row_exists)
|
if (old_row_exists)
|
||||||
{
|
{
|
||||||
@ -2181,7 +2187,7 @@ int grant_init (void)
|
|||||||
delete thd;
|
delete thd;
|
||||||
DBUG_RETURN(0); // Empty table is ok!
|
DBUG_RETURN(0); // Empty table is ok!
|
||||||
}
|
}
|
||||||
grant_option = TRUE;
|
grant_option= TRUE;
|
||||||
t_table->file->index_end();
|
t_table->file->index_end();
|
||||||
|
|
||||||
MEM_ROOT *old_root=my_pthread_getspecific_ptr(MEM_ROOT*,THR_MALLOC);
|
MEM_ROOT *old_root=my_pthread_getspecific_ptr(MEM_ROOT*,THR_MALLOC);
|
||||||
|
@ -612,8 +612,6 @@ bool rename_temporary_table(THD* thd, TABLE *table, const char *db,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* move table first in unused links */
|
/* move table first in unused links */
|
||||||
|
|
||||||
static void relink_unused(TABLE *table)
|
static void relink_unused(TABLE *table)
|
||||||
@ -2144,7 +2142,10 @@ bool remove_table_from_cache(THD *thd, const char *db, const char *table_name,
|
|||||||
THD *in_use;
|
THD *in_use;
|
||||||
table->version=0L; /* Free when thread is ready */
|
table->version=0L; /* Free when thread is ready */
|
||||||
if (!(in_use=table->in_use))
|
if (!(in_use=table->in_use))
|
||||||
|
{
|
||||||
|
DBUG_PRINT("info",("Table was not in use"));
|
||||||
relink_unused(table);
|
relink_unused(table);
|
||||||
|
}
|
||||||
else if (in_use != thd)
|
else if (in_use != thd)
|
||||||
{
|
{
|
||||||
in_use->some_tables_deleted=1;
|
in_use->some_tables_deleted=1;
|
||||||
|
@ -3088,6 +3088,7 @@ my_bool Query_cache::check_integrity(bool not_locked)
|
|||||||
result = 1;
|
result = 1;
|
||||||
break;
|
break;
|
||||||
case Query_cache_block::QUERY:
|
case Query_cache_block::QUERY:
|
||||||
|
{
|
||||||
if (in_list(queries_blocks, block, "query"))
|
if (in_list(queries_blocks, block, "query"))
|
||||||
result = 1;
|
result = 1;
|
||||||
for (TABLE_COUNTER_TYPE j=0; j < block->n_tables; j++)
|
for (TABLE_COUNTER_TYPE j=0; j < block->n_tables; j++)
|
||||||
@ -3102,6 +3103,7 @@ my_bool Query_cache::check_integrity(bool not_locked)
|
|||||||
result = 1;
|
result = 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case Query_cache_block::RES_INCOMPLETE:
|
case Query_cache_block::RES_INCOMPLETE:
|
||||||
// This type of block can be not lincked yet (in multithread environment)
|
// This type of block can be not lincked yet (in multithread environment)
|
||||||
break;
|
break;
|
||||||
|
@ -370,7 +370,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
ulong slave_proxy_id;
|
ulong slave_proxy_id;
|
||||||
NET* slave_net; // network connection from slave -> m.
|
NET* slave_net; // network connection from slave -> m.
|
||||||
uint32 log_pos;
|
my_off_t log_pos;
|
||||||
|
|
||||||
THD();
|
THD();
|
||||||
~THD();
|
~THD();
|
||||||
|
@ -305,6 +305,8 @@ multi_delete::~multi_delete()
|
|||||||
bool multi_delete::send_data(List<Item> &values)
|
bool multi_delete::send_data(List<Item> &values)
|
||||||
{
|
{
|
||||||
int secure_counter= -1;
|
int secure_counter= -1;
|
||||||
|
DBUG_ENTER("multi_delete::send_data");
|
||||||
|
|
||||||
for (table_being_deleted=delete_tables ;
|
for (table_being_deleted=delete_tables ;
|
||||||
table_being_deleted ;
|
table_being_deleted ;
|
||||||
table_being_deleted=table_being_deleted->next, secure_counter++)
|
table_being_deleted=table_being_deleted->next, secure_counter++)
|
||||||
@ -319,13 +321,14 @@ bool multi_delete::send_data(List<Item> &values)
|
|||||||
|
|
||||||
if (secure_counter < 0)
|
if (secure_counter < 0)
|
||||||
{
|
{
|
||||||
|
/* If this is the table we are scanning */
|
||||||
table->status|= STATUS_DELETED;
|
table->status|= STATUS_DELETED;
|
||||||
if (!(error=table->file->delete_row(table->record[0])))
|
if (!(error=table->file->delete_row(table->record[0])))
|
||||||
deleted++;
|
deleted++;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
table->file->print_error(error,MYF(0));
|
table->file->print_error(error,MYF(0));
|
||||||
return 1;
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -334,21 +337,23 @@ bool multi_delete::send_data(List<Item> &values)
|
|||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
error=-1;
|
error=-1;
|
||||||
return 1;
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void multi_delete::send_error(uint errcode,const char *err)
|
void multi_delete::send_error(uint errcode,const char *err)
|
||||||
{
|
{
|
||||||
|
DBUG_ENTER("multi_delete::send_error");
|
||||||
|
|
||||||
/* First send error what ever it is ... */
|
/* First send error what ever it is ... */
|
||||||
::send_error(&thd->net,errcode,err);
|
::send_error(&thd->net,errcode,err);
|
||||||
|
|
||||||
/* If nothing deleted return */
|
/* If nothing deleted return */
|
||||||
if (!deleted)
|
if (!deleted)
|
||||||
return;
|
DBUG_VOID_RETURN;
|
||||||
|
|
||||||
/* Below can happen when thread is killed early ... */
|
/* Below can happen when thread is killed early ... */
|
||||||
if (!table_being_deleted)
|
if (!table_being_deleted)
|
||||||
@ -364,7 +369,10 @@ void multi_delete::send_error(uint errcode,const char *err)
|
|||||||
table_being_deleted == delete_tables) || !not_trans_safe)
|
table_being_deleted == delete_tables) || !not_trans_safe)
|
||||||
ha_rollback_stmt(thd);
|
ha_rollback_stmt(thd);
|
||||||
else if (do_delete)
|
else if (do_delete)
|
||||||
VOID(do_deletes(true));
|
{
|
||||||
|
VOID(do_deletes(1));
|
||||||
|
}
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -375,7 +383,7 @@ void multi_delete::send_error(uint errcode,const char *err)
|
|||||||
1 error
|
1 error
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int multi_delete::do_deletes (bool from_send_error)
|
int multi_delete::do_deletes(bool from_send_error)
|
||||||
{
|
{
|
||||||
int error = 0, counter = 0;
|
int error = 0, counter = 0;
|
||||||
|
|
||||||
@ -432,7 +440,7 @@ bool multi_delete::send_eof()
|
|||||||
thd->proc_info="deleting from reference tables";
|
thd->proc_info="deleting from reference tables";
|
||||||
|
|
||||||
/* Does deletes for the last n - 1 tables, returns 0 if ok */
|
/* Does deletes for the last n - 1 tables, returns 0 if ok */
|
||||||
int error = do_deletes(false); // returns 0 if success
|
int error = do_deletes(0); // returns 0 if success
|
||||||
|
|
||||||
/* reset used flags */
|
/* reset used flags */
|
||||||
thd->proc_info="end";
|
thd->proc_info="end";
|
||||||
|
@ -90,6 +90,7 @@ int mysql_ha_close(THD *thd, TABLE_LIST *tables, bool dont_send_ok)
|
|||||||
static enum enum_ha_read_modes rkey_to_rnext[]=
|
static enum enum_ha_read_modes rkey_to_rnext[]=
|
||||||
{ RNEXT, RNEXT, RPREV, RNEXT, RPREV, RNEXT, RPREV };
|
{ RNEXT, RNEXT, RPREV, RNEXT, RPREV, RNEXT, RPREV };
|
||||||
|
|
||||||
|
|
||||||
int mysql_ha_read(THD *thd, TABLE_LIST *tables,
|
int mysql_ha_read(THD *thd, TABLE_LIST *tables,
|
||||||
enum enum_ha_read_modes mode, char *keyname, List<Item> *key_expr,
|
enum enum_ha_read_modes mode, char *keyname, List<Item> *key_expr,
|
||||||
enum ha_rkey_function ha_rkey_mode, Item *cond,
|
enum ha_rkey_function ha_rkey_mode, Item *cond,
|
||||||
@ -121,6 +122,7 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
|
|||||||
List<Item> list;
|
List<Item> list;
|
||||||
list.push_front(new Item_field(NULL,NULL,"*"));
|
list.push_front(new Item_field(NULL,NULL,"*"));
|
||||||
List_iterator<Item> it(list);
|
List_iterator<Item> it(list);
|
||||||
|
uint num_rows;
|
||||||
it++;
|
it++;
|
||||||
|
|
||||||
insert_fields(thd,tables,tables->db,tables->name,&it);
|
insert_fields(thd,tables,tables->db,tables->name,&it);
|
||||||
@ -136,10 +138,9 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
|
|||||||
if (!lock)
|
if (!lock)
|
||||||
goto err0; // mysql_lock_tables() printed error message already
|
goto err0; // mysql_lock_tables() printed error message already
|
||||||
|
|
||||||
for (uint num_rows=0; num_rows < select_limit; )
|
for (num_rows=0; num_rows < select_limit; )
|
||||||
{
|
|
||||||
switch(mode)
|
|
||||||
{
|
{
|
||||||
|
switch(mode) {
|
||||||
case RFIRST:
|
case RFIRST:
|
||||||
err=keyname ?
|
err=keyname ?
|
||||||
table->file->index_first(table->record[0]) :
|
table->file->index_first(table->record[0]) :
|
||||||
|
215
sql/sql_parse.cc
215
sql/sql_parse.cc
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
|
/* Copyright (C) 2000 MySQL AB
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -55,7 +55,9 @@ extern "C" pthread_mutex_t THR_LOCK_keycache;
|
|||||||
extern "C" int gethostname(char *name, int namelen);
|
extern "C" int gethostname(char *name, int namelen);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int check_for_max_user_connections(const char *user, const char *host, uint max);
|
static int check_for_max_user_connections(const char *user, const char *host, uint max_questions);
|
||||||
|
static bool check_mqh(THD *thd, const char *user, const char *host,
|
||||||
|
uint max_questions);
|
||||||
static void decrease_user_connections(const char *user, const char *host);
|
static void decrease_user_connections(const char *user, const char *host);
|
||||||
static bool check_db_used(THD *thd,TABLE_LIST *tables);
|
static bool check_db_used(THD *thd,TABLE_LIST *tables);
|
||||||
static bool check_merge_table_access(THD *thd, char *db, TABLE_LIST *tables);
|
static bool check_merge_table_access(THD *thd, char *db, TABLE_LIST *tables);
|
||||||
@ -121,101 +123,22 @@ extern pthread_mutex_t LOCK_user_conn;
|
|||||||
|
|
||||||
struct user_conn {
|
struct user_conn {
|
||||||
char *user;
|
char *user;
|
||||||
uint len, connections, questions, max;
|
uint len, connections, questions, max_questions;
|
||||||
time_t intime;
|
time_t intime;
|
||||||
};
|
};
|
||||||
|
|
||||||
static byte* get_key_conn(user_conn *buff, uint *length,
|
|
||||||
my_bool not_used __attribute__((unused)))
|
|
||||||
{
|
|
||||||
*length=buff->len;
|
|
||||||
return (byte*) buff->user;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define DEF_USER_COUNT 50
|
|
||||||
|
|
||||||
static void free_user(struct user_conn *uc)
|
|
||||||
{
|
|
||||||
my_free((char*) uc,MYF(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Check if maximum queries per hour limit has been reached
|
Check if user is ok
|
||||||
** returns 0 if OK.
|
Updates:
|
||||||
*/
|
thd->user, thd->master_access, thd->priv_user, thd->db, thd->db_access
|
||||||
|
|
||||||
static bool check_mqh(THD *thd, const char *user, const char *host,uint max)
|
|
||||||
{
|
|
||||||
uint temp_len;
|
|
||||||
char temp_user[USERNAME_LENGTH+HOSTNAME_LENGTH+2];
|
|
||||||
struct user_conn *uc;
|
|
||||||
if (!user)
|
|
||||||
user="";
|
|
||||||
if (!host)
|
|
||||||
host="";
|
|
||||||
temp_len= (uint) (strxnmov(temp_user, sizeof(temp_user), user, "@", host,
|
|
||||||
NullS) - temp_user);
|
|
||||||
//This would be MUCH faster if there was already temp_user made in THD !!! May I ??
|
|
||||||
(void) pthread_mutex_lock(&LOCK_user_conn);
|
|
||||||
uc = (struct user_conn *) hash_search(&hash_user_connections,
|
|
||||||
(byte*) temp_user, temp_len);
|
|
||||||
if (uc) /* user found ; check for no. of queries */
|
|
||||||
{
|
|
||||||
bool my_start = thd->start_time != 0;
|
|
||||||
time_t check_time = (my_start) ? thd->start_time : time(NULL);
|
|
||||||
if (check_time - uc->intime >= 3600)
|
|
||||||
{
|
|
||||||
uc->questions=(uint)my_start;
|
|
||||||
uc->intime=check_time;
|
|
||||||
}
|
|
||||||
else if (uc->max && ++(uc->questions) > uc->max)
|
|
||||||
{
|
|
||||||
(void) pthread_mutex_unlock(&LOCK_user_conn);
|
|
||||||
send_error(&thd->net,ER_NOT_ALLOWED_COMMAND); // change this to appropriate message
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
struct user_conn *uc= ((struct user_conn*)
|
|
||||||
my_malloc(sizeof(struct user_conn) + temp_len+1,
|
|
||||||
MYF(MY_WME)));
|
|
||||||
if (!uc)
|
|
||||||
{
|
|
||||||
send_error(¤t_thd->net, 0, NullS); // Out of memory
|
|
||||||
(void) pthread_mutex_unlock(&LOCK_user_conn);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
uc->user=(char*) (uc+1);
|
|
||||||
memcpy(uc->user,temp_user,temp_len+1);
|
|
||||||
uc->len = temp_len;
|
|
||||||
uc->connections = 1;
|
|
||||||
uc->questions=0;
|
|
||||||
uc->max=max;
|
|
||||||
uc->intime=current_thd->thr_create_time;
|
|
||||||
if (hash_insert(&hash_user_connections, (byte*) uc))
|
|
||||||
{
|
|
||||||
my_free((char*) uc,0);
|
|
||||||
send_error(¤t_thd->net, 0, NullS); // Out of memory
|
|
||||||
(void) pthread_mutex_unlock(&LOCK_user_conn);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(void) pthread_mutex_unlock(&LOCK_user_conn);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Check if user is ok
|
|
||||||
** Updates:
|
|
||||||
** thd->user, thd->master_access, thd->priv_user, thd->db, thd->db_access
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static bool check_user(THD *thd,enum_server_command command, const char *user,
|
static bool check_user(THD *thd,enum_server_command command, const char *user,
|
||||||
const char *passwd, const char *db, bool check_count)
|
const char *passwd, const char *db, bool check_count)
|
||||||
{
|
{
|
||||||
NET *net= &thd->net;
|
NET *net= &thd->net;
|
||||||
uint max=0;
|
uint max_questions=0;
|
||||||
thd->db=0;
|
thd->db=0;
|
||||||
thd->db_length=0;
|
thd->db_length=0;
|
||||||
|
|
||||||
@ -228,7 +151,7 @@ static bool check_user(THD *thd,enum_server_command command, const char *user,
|
|||||||
passwd, thd->scramble, &thd->priv_user,
|
passwd, thd->scramble, &thd->priv_user,
|
||||||
protocol_version == 9 ||
|
protocol_version == 9 ||
|
||||||
!(thd->client_capabilities &
|
!(thd->client_capabilities &
|
||||||
CLIENT_LONG_PASSWORD),&max);
|
CLIENT_LONG_PASSWORD),&max_questions);
|
||||||
DBUG_PRINT("info",
|
DBUG_PRINT("info",
|
||||||
("Capabilities: %d packet_length: %d Host: '%s' User: '%s' Using password: %s Access: %u db: '%s'",
|
("Capabilities: %d packet_length: %d Host: '%s' User: '%s' Using password: %s Access: %u db: '%s'",
|
||||||
thd->client_capabilities, thd->max_packet_length,
|
thd->client_capabilities, thd->max_packet_length,
|
||||||
@ -259,8 +182,6 @@ static bool check_user(THD *thd,enum_server_command command, const char *user,
|
|||||||
return(1);
|
return(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (mqh_used && max && check_mqh(thd,user,thd->host,max))
|
|
||||||
return -1;
|
|
||||||
mysql_log.write(thd,command,
|
mysql_log.write(thd,command,
|
||||||
(thd->priv_user == thd->user ?
|
(thd->priv_user == thd->user ?
|
||||||
(char*) "%s@%s on %s" :
|
(char*) "%s@%s on %s" :
|
||||||
@ -269,8 +190,11 @@ static bool check_user(THD *thd,enum_server_command command, const char *user,
|
|||||||
thd->host_or_ip,
|
thd->host_or_ip,
|
||||||
db ? db : (char*) "");
|
db ? db : (char*) "");
|
||||||
thd->db_access=0;
|
thd->db_access=0;
|
||||||
|
/* Don't allow user to connect if he has done too many queries */
|
||||||
|
if (max_questions && check_mqh(thd,user,thd->host_or_ip,max_questions))
|
||||||
|
return -1;
|
||||||
if (max_user_connections &&
|
if (max_user_connections &&
|
||||||
check_for_max_user_connections(user, thd->host, max))
|
check_for_max_user_connections(user, thd->host, max_questions))
|
||||||
return -1;
|
return -1;
|
||||||
if (db && db[0])
|
if (db && db[0])
|
||||||
{
|
{
|
||||||
@ -285,30 +209,40 @@ static bool check_user(THD *thd,enum_server_command command, const char *user,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** check for maximum allowable user connections
|
Check for maximum allowable user connections, if the mysqld server is
|
||||||
** if mysql server is started with corresponding
|
started with corresponding variable that is greater then 0.
|
||||||
** variable that is greater then 0
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
static byte* get_key_conn(user_conn *buff, uint *length,
|
||||||
|
my_bool not_used __attribute__((unused)))
|
||||||
|
{
|
||||||
|
*length=buff->len;
|
||||||
|
return (byte*) buff->user;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void free_user(struct user_conn *uc)
|
||||||
|
{
|
||||||
|
my_free((char*) uc,MYF(0));
|
||||||
|
}
|
||||||
|
|
||||||
void init_max_user_conn(void)
|
void init_max_user_conn(void)
|
||||||
{
|
{
|
||||||
(void) hash_init(&hash_user_connections,DEF_USER_COUNT,0,0,
|
(void) hash_init(&hash_user_connections,max_connections,0,0,
|
||||||
(hash_get_key) get_key_conn, (void (*)(void*)) free_user,
|
(hash_get_key) get_key_conn, (void (*)(void*)) free_user,
|
||||||
0);
|
0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int check_for_max_user_connections(const char *user, const char *host, uint max)
|
static int check_for_max_user_connections(const char *user, const char *host,
|
||||||
|
uint max_questions)
|
||||||
{
|
{
|
||||||
int error=1;
|
int error=1;
|
||||||
uint temp_len;
|
uint temp_len;
|
||||||
char temp_user[USERNAME_LENGTH+HOSTNAME_LENGTH+2];
|
char temp_user[USERNAME_LENGTH+HOSTNAME_LENGTH+2];
|
||||||
struct user_conn *uc;
|
struct user_conn *uc;
|
||||||
if (!user)
|
|
||||||
user="";
|
|
||||||
if (!host)
|
|
||||||
host="";
|
|
||||||
DBUG_ENTER("check_for_max_user_connections");
|
DBUG_ENTER("check_for_max_user_connections");
|
||||||
|
DBUG_ASSERT(user != 0);
|
||||||
|
DBUG_ASSERT(host != 0);
|
||||||
DBUG_PRINT("enter",("user: '%s' host: '%s'", user, host));
|
DBUG_PRINT("enter",("user: '%s' host: '%s'", user, host));
|
||||||
|
|
||||||
temp_len= (uint) (strxnmov(temp_user, sizeof(temp_user), user, "@", host,
|
temp_len= (uint) (strxnmov(temp_user, sizeof(temp_user), user, "@", host,
|
||||||
@ -341,7 +275,7 @@ static int check_for_max_user_connections(const char *user, const char *host, ui
|
|||||||
uc->len = temp_len;
|
uc->len = temp_len;
|
||||||
uc->connections = 1;
|
uc->connections = 1;
|
||||||
uc->questions=0;
|
uc->questions=0;
|
||||||
uc->max=max;
|
uc->max_questions=max_questions;
|
||||||
uc->intime=current_thd->thr_create_time;
|
uc->intime=current_thd->thr_create_time;
|
||||||
if (hash_insert(&hash_user_connections, (byte*) uc))
|
if (hash_insert(&hash_user_connections, (byte*) uc))
|
||||||
{
|
{
|
||||||
@ -397,9 +331,82 @@ void free_max_user_conn(void)
|
|||||||
hash_free(&hash_user_connections);
|
hash_free(&hash_user_connections);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** check connnetion and get priviliges
|
Check if maximum queries per hour limit has been reached
|
||||||
** returns 0 on ok, -1 < if error is given > 0 on error.
|
returns 0 if OK.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static bool check_mqh(THD *thd, const char *user, const char *host,
|
||||||
|
uint max_questions)
|
||||||
|
{
|
||||||
|
uint temp_len;
|
||||||
|
char temp_user[USERNAME_LENGTH+HOSTNAME_LENGTH+2];
|
||||||
|
struct user_conn *uc;
|
||||||
|
bool error=0;
|
||||||
|
|
||||||
|
DBUG_ASSERT(user != 0);
|
||||||
|
DBUG_ASSERT(host != 0);
|
||||||
|
|
||||||
|
/* TODO: Add username + host to THD for faster execution */
|
||||||
|
temp_len= (uint) (strxnmov(temp_user, sizeof(temp_user)-1, user, "@", host,
|
||||||
|
NullS) - temp_user);
|
||||||
|
(void) pthread_mutex_lock(&LOCK_user_conn);
|
||||||
|
uc = (struct user_conn *) hash_search(&hash_user_connections,
|
||||||
|
(byte*) temp_user, temp_len);
|
||||||
|
if (uc)
|
||||||
|
{
|
||||||
|
/* user found ; check for no. of queries */
|
||||||
|
bool my_start = thd->start_time != 0;
|
||||||
|
time_t check_time = (my_start) ? thd->start_time : time(NULL);
|
||||||
|
if (check_time - uc->intime >= 3600)
|
||||||
|
{
|
||||||
|
uc->questions=(uint) my_start;
|
||||||
|
uc->intime=check_time;
|
||||||
|
}
|
||||||
|
else if (uc->max_questions && ++(uc->questions) > uc->max_questions)
|
||||||
|
{
|
||||||
|
net_printf(&thd->net, ER_USER_LIMIT_REACHED, temp_user, "max_questions",
|
||||||
|
(long) uc->questions);
|
||||||
|
error=1;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
struct user_conn *uc= ((struct user_conn*)
|
||||||
|
my_malloc(sizeof(struct user_conn) + temp_len+1,
|
||||||
|
MYF(MY_WME)));
|
||||||
|
if (!uc)
|
||||||
|
{
|
||||||
|
send_error(¤t_thd->net, 0, NullS); // Out of memory
|
||||||
|
error=1;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
uc->user=(char*) (uc+1);
|
||||||
|
memcpy(uc->user,temp_user,temp_len+1);
|
||||||
|
uc->len = temp_len;
|
||||||
|
uc->connections = 1;
|
||||||
|
uc->questions=0;
|
||||||
|
uc->max_questions=max_questions;
|
||||||
|
uc->intime=current_thd->thr_create_time;
|
||||||
|
if (hash_insert(&hash_user_connections, (byte*) uc))
|
||||||
|
{
|
||||||
|
my_free((char*) uc,0);
|
||||||
|
send_error(¤t_thd->net, 0, NullS); // Out of memory
|
||||||
|
error=1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
end:
|
||||||
|
(void) pthread_mutex_unlock(&LOCK_user_conn);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Check connnetion and get priviliges
|
||||||
|
Returns 0 on ok, -1 < if error is given > 0 on error.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@ -408,9 +415,7 @@ check_connections(THD *thd)
|
|||||||
{
|
{
|
||||||
uint connect_errors=0;
|
uint connect_errors=0;
|
||||||
NET *net= &thd->net;
|
NET *net= &thd->net;
|
||||||
/*
|
/* Store the connection details */
|
||||||
** store the connection details
|
|
||||||
*/
|
|
||||||
DBUG_PRINT("info", (("check_connections called by thread %d"),
|
DBUG_PRINT("info", (("check_connections called by thread %d"),
|
||||||
thd->thread_id));
|
thd->thread_id));
|
||||||
DBUG_PRINT("info",("New connection received on %s",
|
DBUG_PRINT("info",("New connection received on %s",
|
||||||
|
@ -129,7 +129,7 @@ rename_tables(THD *thd, TABLE_LIST *table_list, bool skip_error)
|
|||||||
if (!access(name,F_OK))
|
if (!access(name,F_OK))
|
||||||
{
|
{
|
||||||
my_error(ER_TABLE_EXISTS_ERROR,MYF(0),name);
|
my_error(ER_TABLE_EXISTS_ERROR,MYF(0),name);
|
||||||
return ren_table; // This can't be skipped
|
DBUG_RETURN(ren_table); // This can't be skipped
|
||||||
}
|
}
|
||||||
sprintf(name,"%s/%s/%s%s",mysql_data_home,
|
sprintf(name,"%s/%s/%s%s",mysql_data_home,
|
||||||
ren_table->db,ren_table->name,
|
ren_table->db,ren_table->name,
|
||||||
@ -138,7 +138,7 @@ rename_tables(THD *thd, TABLE_LIST *table_list, bool skip_error)
|
|||||||
{
|
{
|
||||||
my_error(ER_FILE_NOT_FOUND, MYF(0), name, my_errno);
|
my_error(ER_FILE_NOT_FOUND, MYF(0), name, my_errno);
|
||||||
if (!skip_error)
|
if (!skip_error)
|
||||||
return ren_table;
|
DBUG_RETURN(ren_table);
|
||||||
}
|
}
|
||||||
else if (mysql_rename_table(table_type,
|
else if (mysql_rename_table(table_type,
|
||||||
ren_table->db, ren_table->name,
|
ren_table->db, ren_table->name,
|
||||||
|
@ -763,7 +763,6 @@ int change_master(THD* thd, MASTER_INFO* mi)
|
|||||||
1 /* wait for start*/,
|
1 /* wait for start*/,
|
||||||
mi,master_info_file,relay_log_info_file,
|
mi,master_info_file,relay_log_info_file,
|
||||||
restart_thread_mask);
|
restart_thread_mask);
|
||||||
err:
|
|
||||||
unlock_slave_threads(mi);
|
unlock_slave_threads(mi);
|
||||||
thd->proc_info = 0;
|
thd->proc_info = 0;
|
||||||
if (error)
|
if (error)
|
||||||
@ -1006,9 +1005,9 @@ int log_loaded_block(IO_CACHE* file)
|
|||||||
|
|
||||||
/* file->request_pos contains position where we started last read */
|
/* file->request_pos contains position where we started last read */
|
||||||
char* buffer = (char*) file->request_pos;
|
char* buffer = (char*) file->request_pos;
|
||||||
if (!(block_len = file->read_end - buffer))
|
if (!(block_len = (char*) file->read_end - (char*) buffer))
|
||||||
return 0;
|
return 0;
|
||||||
lf_info = (LOAD_FILE_INFO*)file->arg;
|
lf_info = (LOAD_FILE_INFO*) file->arg;
|
||||||
if (lf_info->last_pos_in_file != HA_POS_ERROR &&
|
if (lf_info->last_pos_in_file != HA_POS_ERROR &&
|
||||||
lf_info->last_pos_in_file >= file->pos_in_file)
|
lf_info->last_pos_in_file >= file->pos_in_file)
|
||||||
return 0;
|
return 0;
|
||||||
@ -1030,5 +1029,3 @@ int log_loaded_block(IO_CACHE* file)
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -185,7 +185,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
|
|||||||
ulong select_options,select_result *result)
|
ulong select_options,select_result *result)
|
||||||
{
|
{
|
||||||
TABLE *tmp_table;
|
TABLE *tmp_table;
|
||||||
int error, tmp_error, tmp;
|
int error, tmp_error;
|
||||||
bool need_tmp,hidden_group_fields;
|
bool need_tmp,hidden_group_fields;
|
||||||
bool simple_order,simple_group,no_order, skip_sort_order;
|
bool simple_order,simple_group,no_order, skip_sort_order;
|
||||||
Item::cond_result cond_value;
|
Item::cond_result cond_value;
|
||||||
|
@ -708,7 +708,7 @@ mysqld_show_keys(THD *thd, TABLE_LIST *table_list)
|
|||||||
|
|
||||||
/* Null flag */
|
/* Null flag */
|
||||||
uint flags= key_part->field ? key_part->field->flags : 0;
|
uint flags= key_part->field ? key_part->field->flags : 0;
|
||||||
char *pos=(byte*) ((flags & NOT_NULL_FLAG) ? "" : "YES");
|
char *pos=(char*) ((flags & NOT_NULL_FLAG) ? "" : "YES");
|
||||||
net_store_data(packet,convert,(const char*) pos);
|
net_store_data(packet,convert,(const char*) pos);
|
||||||
net_store_data(packet,convert,table->file->index_type(i));
|
net_store_data(packet,convert,table->file->index_type(i));
|
||||||
/* Comment */
|
/* Comment */
|
||||||
|
@ -613,10 +613,12 @@ bool multi_update::send_data(List<Item> &values)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Here I insert into each temporary table
|
// Here we insert into each temporary table
|
||||||
values_by_table.push_front(new Item_string(table->file->ref,table->file->ref_length));
|
values_by_table.push_front(new Item_string((char*) table->file->ref,
|
||||||
|
table->file->ref_length));
|
||||||
fill_record(tmp_tables[secure_counter]->field,values_by_table);
|
fill_record(tmp_tables[secure_counter]->field,values_by_table);
|
||||||
error= write_record(tmp_tables[secure_counter],&(infos[secure_counter]));
|
error= write_record(tmp_tables[secure_counter],
|
||||||
|
&(infos[secure_counter]));
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
error=-1;
|
error=-1;
|
||||||
@ -661,7 +663,8 @@ int multi_update::do_updates (bool from_send_error)
|
|||||||
{
|
{
|
||||||
int error = 0, counter = 0;
|
int error = 0, counter = 0;
|
||||||
|
|
||||||
if (num_updated == 1) return 0;
|
if (num_updated == 1)
|
||||||
|
return 0;
|
||||||
if (from_send_error)
|
if (from_send_error)
|
||||||
{
|
{
|
||||||
/* Found out table number for 'table_being_updated' */
|
/* Found out table number for 'table_being_updated' */
|
||||||
@ -690,7 +693,7 @@ int multi_update::do_updates (bool from_send_error)
|
|||||||
}
|
}
|
||||||
List<Item> list;
|
List<Item> list;
|
||||||
Field **ptr=tmp_table->field,*field;
|
Field **ptr=tmp_table->field,*field;
|
||||||
// This is supposed to be something like insert_fields
|
// This is supposed to be something like insert_fields
|
||||||
thd->used_tables|=tmp_table->map;
|
thd->used_tables|=tmp_table->map;
|
||||||
while ((field = *ptr++))
|
while ((field = *ptr++))
|
||||||
{
|
{
|
||||||
@ -709,12 +712,14 @@ int multi_update::do_updates (bool from_send_error)
|
|||||||
(!thd->killed || from_send_error || not_trans_safe))
|
(!thd->killed || from_send_error || not_trans_safe))
|
||||||
{
|
{
|
||||||
found++;
|
found++;
|
||||||
error= table->file->rnd_pos(table->record[0], (*(tmp_table->field))->ptr);
|
error= table->file->rnd_pos(table->record[0],
|
||||||
|
(byte*) (*(tmp_table->field))->ptr);
|
||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
table->status|= STATUS_UPDATED;
|
table->status|= STATUS_UPDATED;
|
||||||
store_record(table,1);
|
store_record(table,1);
|
||||||
error= fill_record(*fields_by_tables[counter + 1],list) /*|| compare_record(table, query_id)*/ ||
|
error= fill_record(*fields_by_tables[counter + 1],list) ||
|
||||||
|
/* compare_record(table, query_id) || */
|
||||||
table->file->update_row(table->record[1],table->record[0]);
|
table->file->update_row(table->record[1],table->record[0]);
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
@ -731,40 +736,47 @@ int multi_update::do_updates (bool from_send_error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* out: 1 if error, 0 if success */
|
||||||
|
|
||||||
bool multi_update::send_eof()
|
bool multi_update::send_eof()
|
||||||
{
|
{
|
||||||
thd->proc_info="updating the reference tables"; /* out: 1 if error, 0 if success */
|
thd->proc_info="updating the reference tables";
|
||||||
|
|
||||||
/* Does updates for the last n - 1 tables, returns 0 if ok */
|
/* Does updates for the last n - 1 tables, returns 0 if ok */
|
||||||
int error = do_updates(false); /* do_updates returns 0 if success */
|
int error = do_updates(false); /* do_updates returns 0 if success */
|
||||||
|
|
||||||
/* reset used flags */
|
/* reset used flags */
|
||||||
// update_tables->table->no_keyread=0;
|
#ifndef NOT_USED
|
||||||
if (error == -1) error = 0;
|
update_tables->table->no_keyread=0;
|
||||||
|
#endif
|
||||||
|
if (error == -1)
|
||||||
|
error = 0;
|
||||||
thd->proc_info="end";
|
thd->proc_info="end";
|
||||||
if (error)
|
if (error)
|
||||||
send_error(error,"An error occured in multi-table update");
|
send_error(error,"An error occured in multi-table update");
|
||||||
|
|
||||||
/* Write the SQL statement to the binlog if we updated
|
/*
|
||||||
|
Write the SQL statement to the binlog if we updated
|
||||||
rows and we succeeded, or also in an error case when there
|
rows and we succeeded, or also in an error case when there
|
||||||
was a non-transaction-safe table involved, since
|
was a non-transaction-safe table involved, since
|
||||||
modifications in it cannot be rolled back. */
|
modifications in it cannot be rolled back.
|
||||||
|
*/
|
||||||
|
|
||||||
if (updated || not_trans_safe)
|
if (updated || not_trans_safe)
|
||||||
{
|
{
|
||||||
mysql_update_log.write(thd,thd->query,thd->query_length);
|
mysql_update_log.write(thd,thd->query,thd->query_length);
|
||||||
Query_log_event qinfo(thd, thd->query);
|
Query_log_event qinfo(thd, thd->query);
|
||||||
|
|
||||||
/* mysql_bin_log is not open if binlogging or replication
|
/*
|
||||||
is not used */
|
mysql_bin_log is not open if binlogging or replication
|
||||||
|
is not used
|
||||||
|
*/
|
||||||
|
|
||||||
if (mysql_bin_log.is_open() && mysql_bin_log.write(&qinfo) &&
|
if (mysql_bin_log.is_open() && mysql_bin_log.write(&qinfo) &&
|
||||||
!not_trans_safe)
|
!not_trans_safe)
|
||||||
error=1; /* Log write failed: roll back
|
error=1; /* Log write failed: roll back the SQL statement */
|
||||||
the SQL statement */
|
|
||||||
|
|
||||||
/* Commit or rollback the current SQL statement */
|
/* Commit or rollback the current SQL statement */
|
||||||
|
|
||||||
VOID(ha_autocommit_or_rollback(thd,error > 0));
|
VOID(ha_autocommit_or_rollback(thd,error > 0));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -577,7 +577,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
|
|||||||
opt_outer table_list table_name opt_option opt_place opt_low_priority
|
opt_outer table_list table_name opt_option opt_place opt_low_priority
|
||||||
opt_attribute opt_attribute_list attribute column_list column_list_id
|
opt_attribute opt_attribute_list attribute column_list column_list_id
|
||||||
opt_column_list grant_privileges opt_table user_list grant_option
|
opt_column_list grant_privileges opt_table user_list grant_option
|
||||||
grant_privilege grant_privilege_list mqh_option
|
grant_privilege grant_privilege_list
|
||||||
flush_options flush_option insert_lock_option replace_lock_option
|
flush_options flush_option insert_lock_option replace_lock_option
|
||||||
equal optional_braces opt_key_definition key_usage_list2
|
equal optional_braces opt_key_definition key_usage_list2
|
||||||
opt_mi_check_type opt_to mi_check_types normal_join
|
opt_mi_check_type opt_to mi_check_types normal_join
|
||||||
@ -3395,7 +3395,7 @@ grant:
|
|||||||
lex->mqh=0;
|
lex->mqh=0;
|
||||||
}
|
}
|
||||||
grant_privileges ON opt_table TO_SYM user_list
|
grant_privileges ON opt_table TO_SYM user_list
|
||||||
require_clause grant_option mqh_option
|
require_clause grant_options
|
||||||
|
|
||||||
grant_privileges:
|
grant_privileges:
|
||||||
grant_privilege_list {}
|
grant_privilege_list {}
|
||||||
@ -3582,17 +3582,19 @@ require_clause: /* empty */
|
|||||||
Lex->ssl_type=SSL_TYPE_X509;
|
Lex->ssl_type=SSL_TYPE_X509;
|
||||||
}
|
}
|
||||||
|
|
||||||
grant_option:
|
grant_options:
|
||||||
/* empty */ {}
|
/* empty */ {}
|
||||||
| WITH GRANT OPTION { Lex->grant |= GRANT_ACL;}
|
| WITH grant_option_list
|
||||||
|
|
||||||
mqh_option:
|
grant_option_list:
|
||||||
/* empty */ {}
|
grant_option_list grant_option {}
|
||||||
| AND WITH MAX_QUERIES_PER_HOUR EQ NUM
|
| grant_option {}
|
||||||
|
|
||||||
|
grant_option:
|
||||||
|
GRANT OPTION { Lex->grant |= GRANT_ACL;}
|
||||||
|
| MAX_QUERIES_PER_HOUR EQ NUM
|
||||||
{
|
{
|
||||||
Lex->mqh=atoi($5.str);
|
Lex->mqh=atoi($3.str);
|
||||||
if (Lex->mqh > 65535)
|
|
||||||
YYABORT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
begin:
|
begin:
|
||||||
|
@ -49,7 +49,8 @@
|
|||||||
X >= 'a' && X <= 'z' ? X-'a'+10 :\
|
X >= 'a' && X <= 'z' ? X-'a'+10 :\
|
||||||
'\177')
|
'\177')
|
||||||
|
|
||||||
char *str2int(register const char *src, register int radix, long int lower, long int upper, long int *val)
|
char *str2int(register const char *src, register int radix, long int lower,
|
||||||
|
long int upper, long int *val)
|
||||||
{
|
{
|
||||||
int sign; /* is number negative (+1) or positive (-1) */
|
int sign; /* is number negative (+1) or positive (-1) */
|
||||||
int n; /* number of digits yet to be converted */
|
int n; /* number of digits yet to be converted */
|
||||||
|
Reference in New Issue
Block a user