diff options
author | unknown <monty@narttu.mysql.fi> | 2000-11-16 00:24:11 +0200 |
---|---|---|
committer | unknown <monty@narttu.mysql.fi> | 2000-11-16 00:24:11 +0200 |
commit | c7d2c59ceb4e3548eb74e5d8fba16e0f41ffc7d9 (patch) | |
tree | 31119bae32d48d3c415144eb5aed588455eefa1a | |
parent | dcf4e49369d91b78ab73b9de038d2729afb3a2a6 (diff) | |
parent | 9a846a52ae62f701c2d54d3f468e2ead393acf91 (diff) | |
download | mariadb-git-c7d2c59ceb4e3548eb74e5d8fba16e0f41ffc7d9.tar.gz |
merge
configure.in:
Auto merged
include/my_sys.h:
Auto merged
libmysql/libmysql.c:
Auto merged
sql/ha_berkeley.cc:
Auto merged
sql/handler.h:
Auto merged
sql/item_strfunc.cc:
Auto merged
sql/lex.h:
Auto merged
sql/mysqld.cc:
Auto merged
sql/sql_class.cc:
Auto merged
sql/sql_insert.cc:
Auto merged
sql/sql_lex.h:
Auto merged
sql/sql_select.cc:
Auto merged
sql/sql_string.h:
Auto merged
BitKeeper/etc/logging_ok:
Auto merged
56 files changed, 1942 insertions, 1502 deletions
diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index bfd5d8f5b39..5bd9eb0bcf2 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -1,8 +1,9 @@ jcole@tetra.bedford.progress.com jcole@tetra.spaceapes.com +monty@narttu.mysql.fi +mwagner@evoq.home.mwagner.org sasha@laptop.slkc.uswest.net sasha@mysql.sashanet.com sasha@work.mysql.com serg@serg.mysql.com yfaktoro@nslinuxw2.bedford.progress.com -mwagner@evoq.home.mwagner.org diff --git a/Docs/manual.texi b/Docs/manual.texi index 7c14318afd8..cdad3c20627 100644 --- a/Docs/manual.texi +++ b/Docs/manual.texi @@ -373,6 +373,7 @@ MySQL Language Reference * ANALYZE TABLE:: @code{ANALYZE TABLE} syntax * REPAIR TABLE:: @code{REPAIR TABLE} syntax * DELETE:: @code{DELETE} syntax +* TRUNCATE:: * SELECT:: @code{SELECT} syntax * JOIN:: @code{JOIN} syntax * INSERT:: @code{INSERT} syntax @@ -591,6 +592,7 @@ Speed of queries that access or update data MySQL Utilites * Programs:: What do the executables do? +* safe_mysqld:: safe_mysqld, the wrapper around mysqld * mysql:: The command line tool * mysqladmin:: Administering a @strong{MySQL} server * mysqldump:: Dumping the structure and data from @strong{MySQL} databases and tables @@ -813,7 +815,7 @@ MySQL change history Changes in release 3.23.x (Recommended; beta) -* News-3.23.28:: Changes in release 3.23.28 +* News-3.23.28:: Changes in release 3.23.28 * News-3.23.27:: Changes in release 3.23.27 * News-3.23.26:: Changes in release 3.23.26 * News-3.23.25:: Changes in release 3.23.25 @@ -2002,6 +2004,8 @@ Hands on tutorial for @strong{MySQL}. The Mac OS Xclave. Running @strong{MySQL} on Mac OS X @item @uref{http://www.prnet.de/RegEx/mysql.html}@* MySQL for Mac OS X Server. +@item @uref{http://www.latencyzero.com/macosx/mysql.html}@* +Bulding MySQL for Mac OS X @item @uref{http://www.lilback.com/macsql/}@* Client libraries for the Macintosh. @end itemize @@ -3606,10 +3610,13 @@ similar system. In the worst case, we may require access to your system to be able to create a binary distribution. @item -If you can provide accommodations and pay for traveler fares, you can even -get a @strong{MySQL} developer to visit you and offer you help with your -troubles. Extended login support entitles you to one personal -encounter per year, but we are always very flexible towards our customers! +If you can provide accommodations and pay for traveler fares, you can +even get a @strong{MySQL} developer to visit you and offer you help with +your troubles. Extended login support entitles you to one personal +encounter per year, but we are always very flexible towards our +customers! If the visit takes 16 hours or more, the first 8 hours is +without charge. For the hours above 8 hours, you will be charged with a +rate that is at least 20 % less than our standard rates. @end itemize @node Installing, Compatibility, Licensing and Support, Top @@ -4940,6 +4947,8 @@ You can start the @strong{MySQL} server with the following command: shell> bin/safe_mysqld --user=mysql & @end example +@xref{safe_mysqld}. + @xref{Post-installation}. @cindex RPM file @@ -6655,7 +6664,7 @@ table. @xref{Crashing}. To get a core dump on Linux if mysqld dies with a SIGSEGV signal, you can start mysqld with the @code{--core-file} option. Note that you also probably need to raise the @code{core file size} by adding -@code{ulimit -c 1000000} to @code{safe_mysqld}. +@code{ulimit -c 1000000} to @code{safe_mysqld}. @xref{safe_mysqld}. If you are using LinuxThreads and @code{mysqladmin shutdown} doesn't work, you must upgrade to LinuxThreads Version 0.7.1 or newer. @@ -7017,6 +7026,7 @@ shell> nohup mysqld [options] & @code{nohup} causes the command following it to ignore any @code{SIGHUP} signal sent from the terminal. Alternatively, start the server by running @code{safe_mysqld}, which invokes @code{mysqld} using @code{nohup} for you. +@xref{safe_mysqld}. If you get a problem when compiling mysys/get_opt.c, just remove the line #define _NO_PROTO from the start of that file! @@ -7271,7 +7281,7 @@ FreeBSD is also known to have a very low default file handle limit. safe_mysqld or raise the limits for the mysqld user in /etc/login.conf (and rebuild it witg cap_mkdb /etc/login.conf.) Also be sure you set the appropriate class for this user in the password file if you are not -using the default (use: chpass mysqld-user-name) +using the default (use: chpass mysqld-user-name). @xref{safe_mysqld}. If you get problems with the current date in @strong{MySQL}, setting the @code{TZ} variable will probably help. @xref{Environment variables}. @@ -7358,7 +7368,7 @@ You can change the directory locations if you wish, or just use the defaults by not specifying any locations. If you have problems with performance under heavy load, try using the -@code{--skip-thread-priority} option to @code{safe_mysqld}! This will run +@code{--skip-thread-priority} option to @code{mysqld}! This will run all threads with the same priority; on BSDI Version 3.1, this gives better performance (at least until BSDI fixes their thread scheduler). @@ -8516,6 +8526,7 @@ mysqld: Can't find file: 'host.frm' The above may also happen with a binary @strong{MySQL} distribution if you don't start @strong{MySQL} by executing exactly @code{./bin/safe_mysqld}! +@xref{safe_mysqld}. You might need to run @code{mysql_install_db} as @code{root}. However, if you prefer, you can run the @strong{MySQL} server as an unprivileged @@ -8829,7 +8840,7 @@ system startup and shutdown, and is described more fully in @ref{Automatic start}. @item By invoking @code{safe_mysqld}, which tries to determine the proper options -for @code{mysqld} and then runs it with those options. +for @code{mysqld} and then runs it with those options. @xref{safe_mysqld}. @item On NT you should install @code{mysqld} as a service as follows: @example @@ -8925,47 +8936,6 @@ the command @code{telnet your-host-name tcp-ip-port-number} and press something is using the TCP/IP port @code{mysqld} is trying to use. See @ref{mysql_install_db} and @ref{Multiple servers}. -The @code{safe_mysqld} script is written so that it normally is able to start -a server that was installed from either a source or a binary version of -@strong{MySQL}, even if these install the server in slightly different -locations. @code{safe_mysqld} expects one of these conditions to be true: - -@itemize @bullet -@item -The server and databases can be found relative to the directory from which -@code{safe_mysqld} is invoked. @code{safe_mysqld} looks under its working -directory for @file{bin} and @file{data} directories (for binary -distributions) or for @file{libexec} and @file{var} directories (for source -distributions). This condition should be met if you execute -@code{safe_mysqld} from your @strong{MySQL} installation directory (for -example, @file{/usr/local/mysql} for a binary distribution). - -@item -If the server and databases cannot be found relative to the working directory, -@code{safe_mysqld} attempts to locate them by absolute pathnames. Typical -locations are @file{/usr/local/libexec} and @file{/usr/local/var}. -The actual locations are determined when the distribution was built from which -@code{safe_mysqld} comes. They should be correct if -@strong{MySQL} was installed in a standard location. -@end itemize - -Because @code{safe_mysqld} will try to find the server and databases relative -to its own working directory, you can install a binary distribution of -@strong{MySQL} anywhere, as long as you start @code{safe_mysqld} from the -@strong{MySQL} installation directory: - -@example -shell> cd mysql_installation_directory -shell> bin/safe_mysqld & -@end example - -If @code{safe_mysqld} fails, even when invoked from the @strong{MySQL} -installation directory, you can modify it to use the path to @code{mysqld} -and the pathname options that are correct for your system. Note that if you -upgrade @strong{MySQL} in the future, your modified version of -@code{safe_mysqld} will be overwritten, so you should make a copy of your -edited version that you can reinstall. - If @code{mysqld} is currently running, you can find out what path settings it is using by executing this command: @@ -9065,7 +9035,7 @@ The @code{mysql.server} script uses the following variables: @findex command-line options @cindex options, command-line @node Command-line options, Option files, Automatic start, Post-installation -@subsection Command-line Options +@subsection mysqld command-line options @code{mysqld} accepts the following command-line options: @@ -10109,6 +10079,7 @@ The following will not yet work in @strong{MySQL}: @example SELECT * FROM table1 WHERE id IN (SELECT id FROM table2); SELECT * FROM table1 WHERE id NOT IN (SELECT id FROM table2); +SELECT * FROM table1 WHERE NOT EXISTS (SELECT id FROM table2 where table1.id=table2.id); @end example However, in many cases you can rewrite the query without a sub-select: @@ -10388,6 +10359,11 @@ unless you do so in a very specific order. It's very easy to do ``allowed'' circular definitions that make the tables impossible to re-create each table with a single create statement, even if the definition works and is usable. + +@item +It's very easy to overlook @code{FOREIGN KEY ... ON DELETE} rules when +one codes an application. It's not unusual that one loses a lot of +important information just because a wrong or misused @code{ON DELETE} rule. @end itemize The only nice aspect of @code{FOREIGN KEY} is that it gives ODBC and some @@ -12612,6 +12588,7 @@ to restart @code{mysqld} with @code{--skip-grant-tables} to run * ANALYZE TABLE:: @code{ANALYZE TABLE} syntax * REPAIR TABLE:: @code{REPAIR TABLE} syntax * DELETE:: @code{DELETE} syntax +* TRUNCATE:: * SELECT:: @code{SELECT} syntax * JOIN:: @code{JOIN} syntax * INSERT:: @code{INSERT} syntax @@ -15224,6 +15201,9 @@ mysql> select BINARY "a" = "A"; @end example @code{BINARY} was introduced in @strong{MySQL} Version 3.23.0. + +Note that in some context @strong{MySQL} will not be able to use the +index efficiently when you cast an indexed column to @code{BINARY}. @end table @findex control flow functions @@ -17702,6 +17682,8 @@ alter_specification: or ADD PRIMARY KEY (index_col_name,...) or ADD UNIQUE [index_name] (index_col_name,...) or ADD FULLTEXT [index_name] (index_col_name,...) + or ADD [CONSTRAINT symbol] FOREIGN KEY index_name (index_col_name,...) + [reference_definition] or ALTER [COLUMN] col_name @{SET DEFAULT literal | DROP DEFAULT@} or CHANGE [COLUMN] old_col_name create_definition or MODIFY [COLUMN] create_definition @@ -17761,6 +17743,9 @@ INDEX} are @strong{MySQL} extensions to ANSI SQL92. @code{MODIFY} is an Oracle extension to @code{ALTER TABLE}. @item +@code{TRUNCATE} is an Oracle extension. @xref{TRUNCATE}. + +@item The optional word @code{COLUMN} is a pure noise word and can be omitted. @item @@ -18116,7 +18101,6 @@ as they are being backed up. If you want to backup several tables as a snapshot, you must first issue @code{LOCK TABLES} obtaining a read lock for each table in the group. - The command returns a table with the following columns: @multitable @columnfractions .35 .65 @@ -18127,6 +18111,8 @@ The command returns a table with the following columns: @item Msg_text @tab The message. @end multitable +Note that @code{BACKUP TABLE} is only available in @strong{MySQL} +version 3.23.25 and later. @findex RESTORE TABLE @node RESTORE TABLE, ANALYZE TABLE, BACKUP TABLE, Reference @@ -18225,7 +18211,7 @@ better than sorting on fixed length keys if you have long @code{char()} keys that compress very good. @findex DELETE -@node DELETE, SELECT, REPAIR TABLE, Reference +@node DELETE, TRUNCATE, REPAIR TABLE, Reference @section @code{DELETE} syntax @example @@ -18237,14 +18223,10 @@ DELETE [LOW_PRIORITY] FROM tbl_name given by @code{where_definition}, and returns the number of records deleted. If you issue a @code{DELETE} with no @code{WHERE} clause, all rows are -deleted. If you do this in @code{AUTOCOMMIT} mode, @strong{MySQL} does -this by recreating the table as an empty table, which is much faster -than deleting each row. In this case, @code{DELETE} returns zero as the -number of affected records. (@strong{MySQL} can't return the number of -rows that were actually deleted, because the recreate is done without -opening the data files. As long as the table definition file -@file{tbl_name.frm} is valid, the table can be recreated this way, even -if the data or index files have become corrupted.). +deleted. If you do this in @code{AUTOCOMMIT} mode, this works as +@code{TRUNCATE}. @xref{TRUNCATE}. One problem with this is that +@code{DELETE} will return zero as the number of affected records, but +this will be fixed in 4.0. If you really want to know how many records are deleted when you are deleting all rows, and are willing to suffer a speed penalty, you can use a @@ -18275,8 +18257,34 @@ returned to the client. This can be used to ensure that a specific the @code{DELETE} command until the number of affected rows is less than the @code{LIMIT} value. +@findex TRUNCATE +@node TRUNCATE, SELECT, DELETE, Reference +@section @code{TRUNCATE} syntax + +@example +TRUNCATE TABLE table_name +@end example + +Is in 3.23 and the same thing as @code{DELETE FROM table_name}. @xref{DELETE}. +The differences are: + +@table @bullet +@item +Implemented as a drop and recreate of the table, which makes this +much faster when deleting many rows. +@item +Not transaction safe; @code{TRUNCATE} will automaticly end the current +transaction as if @code{COMMIT} would have been called. +@item +Doesn't return the number of deleted rows. +@item +As long as the table definition file @file{table_name.frm} is +valid, the table can be recreated this way, even if the data or index +files have become corrupted.. +@end table + @findex SELECT -@node SELECT, JOIN, DELETE, Reference +@node SELECT, JOIN, TRUNCATE, Reference @section @code{SELECT} syntax @c help SELECT @@ -18918,6 +18926,9 @@ record in the table has the same value as a new record on a unique index, the old record is deleted before the new record is inserted. @xref{INSERT, , @code{INSERT}}. +In other words, you can't access the values of the old row from a +@code{REPLACE} statement. + @findex LOAD DATA INFILE @node LOAD DATA, UPDATE, REPLACE, Reference @section @code{LOAD DATA INFILE} syntax @@ -19920,11 +19931,17 @@ call should have more details. Check your OS documentation for the maximum value for this variable. Attempting to set @code{back_log} higher than your operating system limit will be ineffective. +@item @code{basedir} +The value of the @code{--basedir} option. + @item @code{bdb_cache_size} The buffer that is allocated to cache index and rows for @code{BDB} tables. If you don't use @code{BDB} tables, you should set this to 0 or start @code{mysqld} with @code{--skip-bdb} o not waste memory for this cache. +@item @code{bdb_home} +The value of the @code{--bdb-home} option. + @item @code{bdb_lock_max} The maximum number of locks (1000 by default) you can have active on a BDB table. You should increase this if you get errors of type @@ -19932,6 +19949,18 @@ table. You should increase this if you get errors of type transactions or when mysqld has to examine a lot of rows to calculate the query. +@item @code{bdb_logdir} +The value of the @code{--bdb-logdir} option. + +@item @code{bdb_tmpdir} +The value of the @code{--bdb-tmpdir} option. + +@item @code{character_set} +The default character set. + +@item @code{character_sets} +The supported character sets. + @item @code{concurrent_inserts} If @code{ON} (the default), @strong{MySQL} will allow you to use @code{INSERT} on @code{MyISAM} tables at the same time as you run @code{SELECT} queries @@ -19942,14 +19971,8 @@ or @code{--skip-new}. The number of seconds the @code{mysqld} server is waiting for a connect packet before responding with @code{Bad handshake}. -@item @code{delayed_insert_timeout} -How long a @code{INSERT DELAYED} thread should wait for @code{INSERT} -statements before terminating. - -@item @code{delayed_insert_limit} -After inserting @code{delayed_insert_limit} rows, the @code{INSERT -DELAYED} handler will check if there are any @code{SELECT} statements -pending. If so, it allows these to execute before continuing. +@item @code{datadir} +The value of the @code{--datadir} option. @item @code{delay_key_write} If enabled (is on by default), @strong{MySQL} will honor the @@ -19963,14 +19986,22 @@ option this means that all tables will be treated as if they were created with the @code{delay_key_write} option. You can clear this flag by starting @code{mysqld} with @code{--skip-new} or @code{--safe-mode}. +@item @code{delayed_insert_limit} +After inserting @code{delayed_insert_limit} rows, the @code{INSERT +DELAYED} handler will check if there are any @code{SELECT} statements +pending. If so, it allows these to execute before continuing. + +@item @code{delayed_insert_timeout} +How long a @code{INSERT DELAYED} thread should wait for @code{INSERT} +statements before terminating. + @item @code{delayed_queue_size} What size queue (in rows) should be allocated for handling @code{INSERT DELAYED}. If the queue becomes full, any client that does @code{INSERT DELAYED} will wait until there is room in the queue again. @item @code{flush} -This is @code{ON} if you have started @strong{MySQL} with the @code{--flush} -option. +This is @code{ON} if you started @code{mysqld} with @code{--flush}. @item @code{flush_time} If this is set to a non-zero value, then every @code{flush_time} seconds all @@ -20023,14 +20054,35 @@ using @code{delay_key_write}. @xref{SHOW}. To get even more speed when writing many rows at the same time use @code{LOCK TABLES}. @xref{LOCK TABLES, , @code{LOCK TABLES}}. -@item @code{lower_case_table_names} -Change all table names to lower case on disk. +@item @code{language} +The language used for error messages. + +@item @code{large_file_support} +If @code{mysqld} was compiled with options for big file support. + +@item @code{locked_in_memory} +If @code{mysqld} was locked in memory with @code{--memlock} + +@item @code{log} +If logging of all queries is enabled. + +@item @code{log_update} +If the update log is enabled. + +@item @code{log_bin} +If the binary log is enabled. + +@item @code{log_slave_updates} +If the updates from the slave should be logged. @item @code{long_query_time} If a query takes longer than this (in seconds), the @code{Slow_queries} counter will be incremented. If you are using @code{--log-slow-queries}, the query will be logged to the slow query logfile. @xref{Slow query log}. +@item @code{lower_case_table_names} +Table names are stored in lower case on disk. + @item @code{max_allowed_packet} The maximum size of one packet. The message buffer is initialized to @code{net_buffer_length} bytes, but can grow up to @code{max_allowed_packet} @@ -20055,15 +20107,15 @@ statements. If you try to insert data into a new table after all @code{INSERT DELAYED} threads are in use, the row will be inserted as if the @code{DELAYED} attribute wasn't specified. +@item @code{max_heap_table_size} +Don't allow creation of heap tables bigger than this. + @item @code{max_join_size} Joins that are probably going to read more than @code{max_join_size} records return an error. Set this value if your users tend to perform joins without a @code{WHERE} clause that take a long time and return millions of rows. -@item @code{max_heap_table_size} -Don't allow creation of heap tables bigger than this. - @item @code{max_sort_length} The number of bytes to use when sorting @code{BLOB} or @code{TEXT} values (only the first @code{max_sort_length} bytes of each value @@ -20076,6 +20128,9 @@ Maximum number of temporary tables a client can keep open at the same time. @item @code{max_write_lock_count} After this many write locks, allow some read locks to run in between. +@item @code{myisam_recover_options} +The value of the @code{--myisam-recover} option. + @item @code{myisam_sort_buffer_size} The buffer that is allocated when sorting the index when doing a @code{REPAIR} or when creating indexes with @code{CREATE INDEX} or @@ -20088,20 +20143,29 @@ can set it to the expected size of a query. (That is, the expected length of SQL statements sent by clients. If statements exceed this length, the buffer is automatically enlarged, up to @code{max_allowed_packet} bytes.) -@item @code{net_retry_count} -If a read on a communication port is interrupted, retry this many times -before giving up. This value should be quite high on @code{FreeBSD} as -internal interrupts is sent to all threads. - @item @code{net_read_timeout} Number of seconds to wait for more data from a connection before aborting the read. Note that when we don't expect data from a connection, the timeout is defined by @code{write_timeout}. +@item @code{net_retry_count} +If a read on a communication port is interrupted, retry this many times +before giving up. This value should be quite high on @code{FreeBSD} as +internal interrupts is sent to all threads. + @item @code{net_write_timeout} Number of seconds to wait for a block to be written to a connection before aborting the write. +@item @code{pid_file} +The value of the @code{--pid-file} option. + +@item @code{port} +The value of the @code{--port} option. + +@item @code{protocol_version} +The protocol version used by the @code{MySQL} server. + @item @code{record_buffer} Each thread that does a sequential scan allocates a buffer of this size for each table it scans. If you do many sequential scans, you may @@ -20111,6 +20175,15 @@ want to increase this value. The initial allocation of the query buffer. If most of your queries are long (like when inserting blobs), you should increase this! +@item @code{server_id} +The value of the @code{--server-id} option. + +@item @code{skip_locking} +Is OFF if @code{mysqld} uses external locking. + +@item @code{skip_networking} +Is ON if we only allow local (socket) connections. + @item @code{skip_show_databases} This prevents people from doing @code{SHOW DATABASES}, if they don't have the @code{PROCESS_PRIV} privilege. This can improve security if @@ -20121,6 +20194,9 @@ tables other users have. If the creating of the thread longer than this (in seconds), the @code{Slow_launch_threads} counter will be incremented. +@item @code{socket} +The unix socket used by the server. + @item @code{sort_buffer} Each thread that needs to do a sort allocates a buffer of this size. Increase this value for faster @code{ORDER BY} or @code{GROUP BY} @@ -20144,6 +20220,9 @@ connections, fail to perform queries, and be very unreliable. For information about how the table cache works, see @ref{Table cache}. +@item @code{table_type} +The default table type + @item @code{thread_cache_size} How many threads we should keep keep in a cache for reuse. When a client disconnects the clients threads is put in the cache if there @@ -20165,12 +20244,21 @@ The stack size for each thread. Many of the limits detected by the @code{crash-me} test are dependent on this value. The default is large enough for normal operation. @xref{Benchmarks}. +@item @code{timezone} +The timezone for the server. + @item @code{tmp_table_size} If an in-memory temporary table exceeds this size, @strong{MySQL} will automatically convert it to an on-disk @code{MyISAM} table. Increase the value of @code{tmp_table_size} if you do many advanced @code{GROUP BY} queries and you have lots of memory. +@item @code{tmpdir} +The directory used for temporary files and temporary tables. + +@item @code{version} +The version number for the server. + @item @code{wait_timeout} The number of seconds the server waits for activity on a connection before closing it. See also @code{interactive_timeout}. @@ -22003,8 +22091,8 @@ reused when you insert new data into the table. You need enough extra memory for all HEAP tables that you want to use at the same time. @item -To free memory, you should execute @code{DELETE FROM heap_table} or -@code{DROP TABLE heap_table}. +To free memory, you should execute @code{DELETE FROM heap_table}, +@code{TRUNCATE TABLE heap_table} or @code{DROP TABLE heap_table}. @item @strong{MySQL} cannot find out how approximately many rows there are between two values (this is used by the range optimizer to decide which @@ -24974,154 +25062,136 @@ what they do. The old @code{FLUSH} variants still work, though for compatibility. @item -Starting in Version 3.23.21 you can use LOAD TABLE FROM MASTER for network -backup and to set up replication initially. +Starting in Version 3.23.21 you can use @code{LOAD TABLE FROM MASTER} for +network backup and to set up replication initially. @item Starting in Version 3.23.23, you can change masters with @code{CHANGE MASTER -TO } +TO}. @item Starting in Version 3.23.23, you tell the master that updates in certain -databases should not be logged to the binary log with @code{binlog-ignore-db} +databases should not be logged to the binary log with @code{binlog-ignore-db}. @item Starting in Version 3.23.26, you can use @code{replicate-rewrite-db} to tell the slave to apply updates from one database on the master to the one -with a different name on the slave +with a different name on the slave. @item Starting in Version 3.23.28, you can use @code{PURGE MASTER LOGS TO 'log-name'} -to get rid of old logs while the slave is running +to get rid of old logs while the slave is running. @end itemize @node Replication Options, Replication SQL, Replication Features, Replication @section Replication Options in my.cnf -The table below explains the replications options in @code{my.cnf} . All -of the are available starting in Version 3.23.15 unless indicated otherwise. +If you are using replication, we recommend you to use MySQL Version 3.23.27 or +later. + +On both master and slave you need to use the @code{server-id} option. +This sets an unique replication id. You should pick a unique value in the +range between 1 to 2^32-1 for each master and slave. +Example: @code{server-id=3} + +The following table has the options you can use for the @strong{MASTER}: @multitable @columnfractions .3 .7 @item @strong{Option} @tab @strong{Description} -@item -@code{log-bin} - @tab Should be set on the master. Tells it to keep a binary update log. -If a parameter is specified, the log will be written to the specified -location. Note that if you give it a parameter with an extention -(eg. @code{log-bin=/mysql/logs/replication.log} ) versions up to -3.23.24 will not work right during replication if you do -@code{FLUSH LOGS} . The problem is fixed -in Version 3.23.25. If you are using this kind of log name, @code{FLUSH LOGS} -will be ignored on binlog. To clear the log, run @code{FLUSH MASTER}, -and do not forget to run @code{FLUSH SLAVE} on all slaves. In Version 3.23.26 -and later versions you should use @code{RESET MASTER} and @code{RESET -SLAVE} - -@item -@code{log-bin-index} - @tab Because the user could issue @code{FLUSH LOGS} command, we need to +@item @code{log-bin=filename} @tab +Write to a binary update log to the specified location. Note that if you +give it a parameter with an extension +(eg. @code{log-bin=/mysql/logs/replication.log} ) versions up to 3.23.24 +will not work right during replication if you do @code{FLUSH LOGS} . The +problem is fixed in 3.23.25. If you are using this kind of log name, +@code{FLUSH LOGS} will be ignored on binlog. To clear the log, run +@code{FLUSH MASTER}, and do not forget to run @code{FLUSH SLAVE} on all +slaves. In 3.23.26 and later versions you should use @code{RESET MASTER} +and @code{RESET SLAVE} + +@item @code{log-bin-index=filename} @tab +Because the user could issue @code{FLUSH LOGS} command, we need to know which log is currently active and which ones have been rotated out and it what sequence. This info is stored in the binary log index file. -The default is `hostname`.index . You can use this option -if you want to be a rebel. -(Set on @strong{Master}, Example: @code{log-bin-index=db.index}) +The default is `hostname`.index . You can use this option if you want to +be a rebel. (Example: @code{log-bin-index=db.index}) -@item -@code{master-host} - @tab Master hostname or IP address for replication. If not set, the slave -thread will not be started. -(Set on @strong{Slave}, Example: @code{master-host=db-master.mycompany.com}) +@item @code{sql-bin-update-same} @tab +If set, setting @code{SQL_LOG_BIN} to a value will automatically set +@code{SQL_LOG_UPDATE} to the same value and vice versa. -@item -@code{master-user} - @tab The user the slave thread will authenticate as when connecting to -the master. The user must have @code{FILE} privilige. If the master user -is not set, user @code{test} is assumed. -(Set on @strong{Slave}, Example: @code{master-user=scott}) +@item @code{binlog-do-db=database_name} @tab +Tells the master it should log updates for the specified database, and +exclude all others not explicitly mentioned. +(Example: @code{binlog-do-db=some_database}) -@item -@code{master-password} - @tab The password the slave thread will authenticate with when connecting -to the master. If not set, empty password is assumed -(Set on @strong{Slave}, Example: @code{master-password=tiger}) +@item @code{binlog-ignore-db=database_name} @tab +Tells the master that updates to the given database should not be logged +to the binary log (Example: @code{binlog-ignore-db=some_database}) +@end multitable -@item -@code{master-port} - @tab The port the master is listening on. If not set, the compiled setting -of @code{MYSQL_PORT} is assumed. If you have not tinkered with @code{configure} -options, this should be 3306. -(Set on @strong{Slave}, Example: @code{master-port=3306}) +The following table has the options you can use for the @strong{SLAVE}: -@item -@code{master-connect-retry} - @tab The number of seconds the slave thread will sleep before retrying to -connect to the master in case the master goes down or the connection is lost. -Default is 60. -(Set on @strong{Slave}, Example: @code{master-connect-retry=60}) +@multitable @columnfractions .3 .7 -@item -@code{master-info-file} - @tab The location of the file that remembers where we left off on the master +@item @strong{Option} @tab @strong{Description} +@item @code{master-host=host} @tab +Master hostname or IP address for replication. If not set, the slave +thread will not be started. +(Example: @code{master-host=db-master.mycompany.com}) + +@item @code{master-user=username} @tab +The user the slave thread will us for authentication when connecting to +the master. The user must have @code{FILE} privilege. If the master user +is not set, user @code{test} is assumed. (Example: +@code{master-user=scott}) + +@item @code{master-password=password} @tab +The password the slave thread will authenticate with when connecting to +the master. If not set, an empty password is assumed (Example: +@code{master-password=tiger}) + +@item @code{master-port=portnumber} @tab +The port the master is listening on. If not set, the compiled setting of +@code{MYSQL_PORT} is assumed. If you have not tinkered with +@code{configure} options, this should be 3306. (Example: +@code{master-port=3306}) + +@item @code{master-connect-retry=seconds} @tab +The number of seconds the slave thread will sleep before retrying to +connect to the master in case the master goes down or the connection is +lost. Default is 60. (Example: @code{master-connect-retry=60}) + +@item @code{master-info-file=filename} @tab +The location of the file that remembers where we left off on the master during the replication process. The default is master.info in the data directory. Sasha: The only reason I see for ever changing the default -is the desire to be rebelious. -(Set on @strong{Slave}, Example: @code{master-info-file=master.info}) - -@item -@code{replicate-do-db} - @tab Tells the slave thread to restrict replication to the specified database. -To specify more than one database, use the directive multiple times, once for -each database. Note that this will only work if you do not use cross-database -queries such as @code{UPDATE some_db.some_table SET foo='bar'} while having -selected a different or no database. -(Set on @strong{Slave}, Example: @code{replicate-do-db=some_db}) - -@item -@code{replicate-ignore-db} - @tab Tells the slave thread to not replicate to the specified database. To -specify more than one database to ignore, use the directive multiple times, -once for each database. You must not use cross database updates for this -option. -(Set on @strong{Slave}, Example: @code{replicate-ignore-db=some_db}) - -@item -@code{sql-bin-update-same} - @tab If set, setting @code{SQL_LOG_BIN} to a value will automatically set -@code{SQL_LOG_UPDATE} to the same value and vice versa. -(Set on @strong{Master}, Example: @code{sql-bin-update-same}) - -@item -@code{log-slave-updates} - @tab Tells the slave to log the updates from the slave thread to the binary -log. Off by default. You will need to turn it on if you plan to daisy-chain -the slaves -(Set on @strong{Slave}, Example: @code{log-slave-updates}) - -@item -@code{binlog-do-db} - @tab Tells the master it should log updates for the specified database, and -exclude all others not explicitly mentioned. -(Set on @strong{Master}, Example: @code{binlog-do-db=some_database}) - -@item -@code{binlog-ignore-db} - @tab Tells the master that updates to the given database should not be logged -to the binary log -(Set on @strong{Master}, Example: @code{binlog-ignore-db=some_database}) - -@item -@code{replicate-rewrite-db} - @tab Tells the slave to apply updates to a database with a different -name than the original ( Set on @strong{Slave}, Example: +is the desire to be rebelious. (Example: +@code{master-info-file=master.info}) + +@item @code{replicate-do-db=database_name} @tab +Tells the slave thread to restrict replication to the specified database. +To specify more than one database, use the directive multiple times, +once for each database. Note that this will only work if you do not use +cross-database queries such as @code{UPDATE some_db.some_table SET +foo='bar'} while having selected a different or no database. +(Example: @code{replicate-do-db=some_db}) + +@item @code{replicate-ignore-db=database_name} @tab +Tells the slave thread to not replicate to the specified database. To +specify more than one database to ignore, use the directive multiple +times, once for each database. This option will not work if you use cross +database updates. (Example: @code{replicate-ignore-db=some_db}) + +@item @code{log-slave-updates} @tab +Tells the slave to log the updates from the slave thread to the binary +log. Off by default. You will need to turn it on if you plan to +daisy-chain the slaves. + +@item @code{replicate-rewrite-db=from_name->to_name} @tab +Updates to a database with a different name than the original (Example: @code{replicate-rewrite-db=master_db_name->slave_db_name} -@item -@code{skip-slave-start} - @tab Tells the slave server not to start the slave on the startup. -The user can start it later with @code{SLAVE START} - -@item -@code{server-id} - @tab Sets the unique replicaiton numeric server id. You should pick one to assign. -The range is from 1 to 2^32-1. (Set on both @strong{Master} and -@strong{Slave}. Example: @code{server-id=3}) +@item @code{skip-slave-start} @tab +Tells the slave server not to start the slave on the startup. The user +can start it later with @code{SLAVE START}. @end multitable @cindex SQL commands, replication @@ -26183,7 +26253,7 @@ This can be done with the following code: @example mysql> LOCK TABLES real_table WRITE, insert_table WRITE; mysql> insert into real_table select * from insert_table; -mysql> delete from insert_table; +mysql> TRUNCATE TABLE insert_table; mysql> UNLOCK TABLES; @end example @@ -27037,13 +27107,13 @@ it is very important to @code{OPTIMIZE TABLE} sometimes. @node Delete speed, , Update speed, Query Speed @subsection Speed of @code{DELETE} queries +If you want to delete all rows in the table, you should use +@code{TRUNCATE TABLE table_name}. @xref{TRUNCATE}. + The time to delete a record is exactly proportional to the number of indexes. To delete records more quickly, you can increase the size of the index cache. @xref{Server parameters}. -It's also much faster to remove all rows than to remove a big part of the -rows from a table. - @cindex optimization, tips @cindex tips, optimization @node Tips, Benchmarks, Query Speed, Performance @@ -27074,7 +27144,7 @@ In some cases it may make sense to introduce a column that is 'hashed' based on information from other columns. If this column is short and reasonably unique it may be much faster than a big index on many columns. In @strong{MySQL} its very easy to use this extra column: -@code{SELECT * FROM table_name WHERE hash=MP5(concat(col1,col2)) +@code{SELECT * FROM table_name WHERE hash=MD5(concat(col1,col2)) AND col_1='constant' AND col_2='constant'} @item For tables that changes a lot you should try to avoid all @code{VARCHAR} @@ -27512,6 +27582,7 @@ How big a @code{VARCHAR} column can be @menu * Programs:: What do the executables do? +* safe_mysqld:: * mysql:: The command line tool * mysqladmin:: Administering a @strong{MySQL} server * mysqldump:: Dumping the structure and data from @strong{MySQL} databases and tables @@ -27522,7 +27593,7 @@ How big a @code{VARCHAR} column can be @cindex environment variables @cindex programs, list of -@node Programs, mysql, Tools, Tools +@node Programs, safe_mysqld, Tools, Tools @section Overview of the different MySQL programs All @strong{MySQL} clients that communicate with the server using the @@ -27643,20 +27714,106 @@ swaps @code{a} and @code{b} in the given files: @example shell> replace a b b a -- file1 file2 ... @end example +@end table +@cindex tools, safe_mysqld +@cindex scripts @cindex @code{safe_mysqld} +@node safe_mysqld, mysql, Programs, Tools +@section safe_mysqld, the wrapper around mysqld + +@code{safe_mysqld} is the recommended way to start a @code{mysqld} +daemon on Unix. @code{safe_mysqld} adds some safety features such as +restarting the server when an error occurs and logging runtime +information to a log file. + +Normally one should never edit the @code{safe_mysqld} script, but +instead put the options to @code{safe_mysqld} in the +@code{[safe_mysqld]} section in the @code{my.cnf} +file. @code{safe_mysqld} will read all options from the @code{[mysqld]} +and @code{[safe_mysqld]} sections from the option files. +@xref{Option files}. + +Note that all options on the command line to @code{safe_mysqld} are passed +to @code{mysqld}. If you wants to use any options in @code{safe_mysqld} that +@code{mysqld} doesn't support, you must specify these in the option file. + +Most of the options to @code{safe_mysqld} are the same as the options to +@code{mysqld}. @xref{Command-line options}. -@item safe_mysqld -A script that starts the @code{mysqld} daemon with some safety features, such -as restarting the server when an error occurs and logging runtime information -to a log file. +@code{safe_mysqld} supports the following options: + +@table @code +@item --basedir=path +@item --core-file-size=# +@item --defaults-extra-file=path +@item --defaults-file=path +@item --open-files=# +Size of the core file @code{mysqld} should be able to create. Passed to +@code{ulimit -c}. +@item --datadir=path +@item --err-log=path +@item --ledir=path +Path to @code{mysqld} +@item --log=path +@item --no-defaults +@item --open-files=# +Number of files @code{mysqld} should be able to open. Passed to +@code{ulimit -n}. +@item --pid-file=path +@item --port=# +@item --socket=path +@item --timezone=# +Set the timezone (the @code{TZ}) variable to the value of this parameter. +@item --user=# @end table +The @code{safe_mysqld} script is written so that it normally is able to start +a server that was installed from either a source or a binary version of +@strong{MySQL}, even if these install the server in slightly different +locations. @code{safe_mysqld} expects one of these conditions to be true: + +@itemize @bullet +@item +The server and databases can be found relative to the directory from which +@code{safe_mysqld} is invoked. @code{safe_mysqld} looks under its working +directory for @file{bin} and @file{data} directories (for binary +distributions) or for @file{libexec} and @file{var} directories (for source +distributions). This condition should be met if you execute +@code{safe_mysqld} from your @strong{MySQL} installation directory (for +example, @file{/usr/local/mysql} for a binary distribution). + +@item +If the server and databases cannot be found relative to the working directory, +@code{safe_mysqld} attempts to locate them by absolute pathnames. Typical +locations are @file{/usr/local/libexec} and @file{/usr/local/var}. +The actual locations are determined when the distribution was built from which +@code{safe_mysqld} comes. They should be correct if +@strong{MySQL} was installed in a standard location. +@end itemize + +Because @code{safe_mysqld} will try to find the server and databases relative +to its own working directory, you can install a binary distribution of +@strong{MySQL} anywhere, as long as you start @code{safe_mysqld} from the +@strong{MySQL} installation directory: + +@example +shell> cd mysql_installation_directory +shell> bin/safe_mysqld & +@end example + +If @code{safe_mysqld} fails, even when invoked from the @strong{MySQL} +installation directory, you can modify it to use the path to @code{mysqld} +and the pathname options that are correct for your system. Note that if you +upgrade @strong{MySQL} in the future, your modified version of +@code{safe_mysqld} will be overwritten, so you should make a copy of your +edited version that you can reinstall. + @cindex command line tool @cindex tools, command line @cindex scripts @cindex @code{mysql} -@node mysql, mysqladmin, Programs, Tools +@node mysql, mysqladmin, safe_mysqld, Tools @section The command line tool @code{mysql} is a simple SQL shell (with GNU @code{readline} capabilities). @@ -29666,10 +29823,13 @@ Use the table description file to create new (empty) data and index files: @example shell> mysql db_name mysql> SET AUTOCOMMIT=1; -mysql> DELETE FROM tbl_name; +mysql> TRUNCATE TABLE table_name; mysql> quit @end example +If your SQL version doesn't have @code{TRUNCATE}, use @code{DELETE FROM +table_name} instead. + @item Copy the old data file back onto the newly created data file. (Don't just move the old file back onto the new file; you want to retain @@ -32650,7 +32810,7 @@ something like this: @example shell> ./configure --with-tcp-port=port_number \ - --with-unix-socket=file_name \ + --with-unix-socket-path=file_name \ --prefix=/usr/local/mysql-3.22.9 @end example @@ -34661,7 +34821,9 @@ The specified group in the option file may contain the following options: @item @code{port} @tab Default port number. @item @code{return-found-rows} @tab Tell @code{mysql_info()} to return found rows instead of updated rows when using @code{UPDATE}. @item @code{socket} @tab Default socket number. -@item @code{timeout} @tab Connect timeout in seconds. +@item +@code{timeout} @tab Connect timeout in seconds. On Linux this timeout also +is used for waiting for the first answer from the server. @item @code{user} @tab Default user. @end multitable @@ -34871,14 +35033,20 @@ client library that uses a different protocol version. This can happen if you use a very old client library to connect to a new server that wasn't started with the @code{--old-protocol} option. -@item CR_NAMEDPIPEOPEN_ERROR; +@item CR_NAMEDPIPEOPEN_ERROR Failed to create a named pipe on Windows. -@item CR_NAMEDPIPEWAIT_ERROR; +@item CR_NAMEDPIPEWAIT_ERROR Failed to wait for a named pipe on Windows. -@item CR_NAMEDPIPESETSTATE_ERROR; +@item CR_NAMEDPIPESETSTATE_ERROR Failed to get a pipe handler on Windows. + +@item CR_SERVER_LOST +If @code{timeout} > 0 and it took longer then @code{timeout} seconds to +connect to the server or if the server died while executing the +@code{init-command}. + @end table @subsubheading Example @@ -37494,6 +37662,10 @@ Fernandez Herrero. @itemize @bullet @item Graphical clients @itemize @bullet +@item @uref{http://www.ideit.com/products/dbvis: DbVisualizer} +Freeware JDBC client to graphically visualize the data and structure +of several databases simultaneously. By Innovative-IT Development AB. + @item @uref{http://www.mysql.com/download_clients.html, mysqlgui homepage} The @strong{MySQL} GUI client homepage. By Sinisa at MySQL AB. @item @uref{http://www.mysql.com/Downloads/Contrib/kmysqladmin-0.4.1.tar.gz, kmysqladmin-0.4.1.tar.gz} @@ -37914,6 +38086,13 @@ Prints the storage usage of a @strong{MySQL} database. sprintf() function for SQL queries that can escape blobs. By Chunhua Liu. @end itemize +@appendixsec Windows programs +@itemize @bullet +@item @uref{http://www.mysql.com/Downloads/Contrib/LaunchMySQL.zip, LaunchMySQL.zip} +The program launches the @strong{MySQL} server, shuts it down, and +display status information. By Bill Thompson +@end itemize + @appendixsec Uncategorized @itemize @bullet @@ -38304,10 +38483,35 @@ though, so Version 3.23 is not released as a stable version yet. @appendixsubsec Changes in release 3.23.28 @itemize @bullet @item +Changed all log files to use our own IO_CACHE mechanism instead of +FILE:s to avoid OS problems when there is many files open. +@item +Added options @code{--open-files} and @code{--timezone} to @code{safe_mysqld}. +@item +Fixed fatal bug in @code{CREATE TEMPORARY TABLE ...SELECT ...}. +@item +Fixed problem with @code{CREATE TABLE .. SELECT NULL}. +@item +Added status variables @code{large_file_support},@code{net_read_timeout}, +@code{net_write_timeout} and @code{query_buffer_size} to @code{SHOW VARIABLES}. +@item +Fixed bug where we didn't allow an index name after the +@code{FOREIGN KEY} definition. +@item +Added @code{TRUNCATE TABLE table_name} as a synonym for +@code{DELETE FROM table_name}. +@item Fixed bug in a BDB key compare function when comparing part keys. @item Added variable @code{bdb_lock_max} to @code{mysqld}. @item +Added more tests to the benchmark suite. +@item +Fixed a overflow bug in the client code when using too long database names. +@item +@code{mysql_connect()} now aborts on Linux if the server doesn't answer in +@code{timeout} seconds. +@item @code{SLAVE START} did not work if you started with @code{--skip-slave-start} and had not explicitly run @code{CHANGE MASTER TO}. @@ -38325,7 +38529,7 @@ shortage when compiled @code{--with-debug=full} Fixed several coredumps in out-of-memory conditions @item @code{SHOW SLAVE STATUS} was using unititialized mutex if the slave had -not been started yet +not been started yet @item Fixed bug in @code{ELT()} and @code{MAKE_SET()} when the query used a temporary table @@ -38335,7 +38539,6 @@ set it to 0 instead of 4 and hit the magic number in the master binlog. @item @code{ALTER TABLE ... ORDER BY ...} syntax added. This will create the new table with the rows in a specific order. - @end itemize @node News-3.23.27, News-3.23.26, News-3.23.28, News-3.23.x @@ -40726,8 +40929,8 @@ The @code{mysql_real_connect()} call is changed to: @example mysql_real_connect(MYSQL *mysql, const char *host, const char *user, - const char *passwd, const char *db, uint port, - const char *unix_socket, uint client_flag) + const char *passwd, const char *db, uint port, + const char *unix_socket, uint client_flag) @end example @item Each connection is handled by its own thread, rather than by the @@ -41854,7 +42057,7 @@ Fixed bug that you couldn't use @code{tbl_name.field_name} in @code{UPDATE}. Fixed @code{SELECT DISTINCT} when using 'hidden group'. For example: @example mysql> SELECT DISTINCT MOD(some_field,10) FROM test - GROUP BY some_field; + GROUP BY some_field; @end example Note: @code{some_field} is normally in the @code{SELECT} part. ANSI SQL should require it. @@ -41927,8 +42130,8 @@ New range optimizer that can resolve ranges when some keypart prefix is constant. Example: @example mysql> SELECT * FROM tbl_name - WHERE key_part_1="customer" - AND key_part_2>=10 AND key_part_2<=10; + WHERE key_part_1="customer" + AND key_part_2>=10 AND key_part_2<=10; @end example @end itemize @@ -42368,7 +42571,7 @@ lookups. The column that is used should be a constant for each group because the value is calculated only once for the first row that is found for a group. @example mysql> SELECT id,lookup.text,sum(*) FROM test,lookup - WHERE test.id=lookup.id GROUP BY id; + WHERE test.id=lookup.id GROUP BY id; @end example @item Fixed bug in @code{SUM(function)} (could cause a core dump). @@ -42744,6 +42947,8 @@ Allow users to change startup options. @item Subqueries. @code{select id from t where grp in (select grp from g where u > 100)} @item +Don't allow more than # threads to run MyISAM recover at the same time. +@item @code{INSERT SQL_CONCURRENT ...}; This will force the insert to happen at the end of the data file if the table is in use by an select to allow concurrent inserts. @@ -42954,6 +43159,10 @@ insert into t1 values (now()); create table t2 select max(a) from t1; show columns from t2; @end example +@item +Come up with a nice syntax for a statement that will @code{UPDATE} the row +if it exists and @code{INSERT} a new row if the row didn't exist. +(Like @code{REPLACE} works with @code{INSERT} / @code{DELETE}) @end itemize @node TODO sometime, TODO unplanned, TODO future, TODO @@ -43960,17 +44169,17 @@ All new development is concentrated to @strong{MySQL}. @appendix GNU General Public License @example - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 675 Mass Ave, Cambridge, MA 02139, USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. +Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA +Everyone is permitted to copy and distribute verbatim copies +of this license document, but changing it is not allowed. - Preamble + Preamble - The licenses for most software are designed to take away your +The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This @@ -43980,48 +44189,48 @@ using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. - When we speak of free software, we are referring to freedom, not +When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. - To protect your rights, we need to make restrictions that forbid +To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. - For example, if you distribute copies of such a program, whether +For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. - We protect your rights with two steps: (1) copyright the software, and +We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. - Also, for each author's protection and ours, we want to make certain +Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. - Finally, any free program is threatened constantly by software +Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. - The precise terms and conditions for copying, distribution and +The precise terms and conditions for copying, distribution and modification follow. - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + GNU GENERAL PUBLIC LICENSE +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - 0. This License applies to any program or other work which contains +0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" @@ -44038,7 +44247,7 @@ is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. - 1. You may copy and distribute verbatim copies of the Program's +1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the @@ -44049,29 +44258,29 @@ along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. - 2. You may modify your copy or copies of the Program or any portion +2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) +a) You must cause the modified files to carry prominent notices +stating that you changed the files and the date of any change. + +b) You must cause any work that you distribute or publish, that in +whole or in part contains or is derived from the Program or any +part thereof, to be licensed as a whole at no charge to all third +parties under the terms of this License. + +c) If the modified program normally reads commands interactively +when run, you must cause it, when started running for such +interactive use in the most ordinary way, to print or display an +announcement including an appropriate copyright notice and a +notice that there is no warranty (or else, saying that you provide +a warranty) and that users may redistribute the program under +these conditions, and telling the user how to view a copy of this +License. (Exception: if the Program itself is interactive but +does not normally print such an announcement, your work based on +the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, @@ -44093,26 +44302,26 @@ with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. - 3. You may copy and distribute the Program (or a work based on it, +3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, +a) Accompany it with the complete corresponding machine-readable +source code, which must be distributed under the terms of Sections +1 and 2 above on a medium customarily used for software interchange; or, - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, +b) Accompany it with a written offer, valid for at least three +years, to give any third party, for a charge no more than your +cost of physically performing source distribution, a complete +machine-readable copy of the corresponding source code, to be +distributed under the terms of Sections 1 and 2 above on a medium +customarily used for software interchange; or, - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) +c) Accompany it with the information you received as to the offer +to distribute corresponding source code. (This alternative is +allowed only for noncommercial distribution and only if you +received the program in object code or executable form with such +an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source @@ -44131,7 +44340,7 @@ access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. - 4. You may not copy, modify, sublicense, or distribute the Program +4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. @@ -44139,7 +44348,7 @@ However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. - 5. You are not required to accept this License, since you have not +5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by @@ -44148,7 +44357,7 @@ Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. - 6. Each time you redistribute the Program (or any work based on the +6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further @@ -44156,7 +44365,7 @@ restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. - 7. If, as a consequence of a court judgment or allegation of patent +7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not @@ -44188,7 +44397,7 @@ impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. - 8. If the distribution and/or use of the Program is restricted in +8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding @@ -44196,7 +44405,7 @@ those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. - 9. The Free Software Foundation may publish revised and/or new versions +9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. @@ -44209,7 +44418,7 @@ Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. - 10. If you wish to incorporate parts of the Program into other free +10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes @@ -44217,9 +44426,9 @@ make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. - NO WARRANTY + NO WARRANTY - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED @@ -44229,7 +44438,7 @@ TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING @@ -44239,45 +44448,45 @@ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - END OF TERMS AND CONDITIONS + END OF TERMS AND CONDITIONS - Appendix: How to Apply These Terms to Your New Programs +Appendix: How to Apply These Terms to Your New Programs - If you develop a new program, and you want it to be of the greatest +If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. - To do so, attach the following notices to the program. It is safest +To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. - <one line to give the program's name and a brief idea of what it does.> - Copyright (C) 19yy <name of author> +<one line to give the program's name and a brief idea of what it does.> +Copyright (C) 19yy <name of author> - 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 - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. +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 +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: - Gnomovision version 69, Copyright (C) 19yy name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. +Gnomovision version 69, Copyright (C) 19yy name of author +Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. +This is free software, and you are welcome to redistribute it +under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may @@ -44288,11 +44497,11 @@ You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. +Yoyodyne, Inc., hereby disclaims all copyright interest in the program +`Gnomovision' (which makes passes at compilers) written by James Hacker. - <signature of Ty Coon>, 1 April 1989 - Ty Coon, President of Vice +<signature of Ty Coon>, 1 April 1989 +Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may @@ -44308,42 +44517,42 @@ Public License instead of this License. @appendix GNU Library General Public License @example - GNU LIBRARY GENERAL PUBLIC LICENSE - Version 2, June 1991 + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 - Copyright (C) 1991 Free Software Foundation, Inc. - 675 Mass Ave, Cambridge, MA 02139, USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. +Copyright (C) 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA +Everyone is permitted to copy and distribute verbatim copies +of this license document, but changing it is not allowed. [This is the first released version of the library GPL. It is - numbered 2 because it goes with version 2 of the ordinary GPL.] +numbered 2 because it goes with version 2 of the ordinary GPL.] - Preamble + Preamble - The licenses for most software are designed to take away your +The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. - This license, the Library General Public License, applies to some +This license, the Library General Public License, applies to some specially designated Free Software Foundation software, and to any other libraries whose authors decide to use it. You can use it for your libraries, too. - When we speak of free software, we are referring to freedom, not +When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. - To protect your rights, we need to make restrictions that forbid +To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library, or if you modify it. - For example, if you distribute copies of the library, whether gratis +For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link a program with the library, you must provide @@ -44351,32 +44560,32 @@ complete object files to the recipients so that they can relink them with the library, after making changes to the library and recompiling it. And you must show them these terms so they know their rights. - Our method of protecting your rights has two steps: (1) copyright +Our method of protecting your rights has two steps: (1) copyright the library, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the library. - Also, for each distributor's protection, we want to make certain +Also, for each distributor's protection, we want to make certain that everyone understands that there is no warranty for this free library. If the library is modified by someone else and passed on, we want its recipients to know that what they have is not the original version, so that any problems introduced by others will not reflect on the original authors' reputations. - Finally, any free program is threatened constantly by software +Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that companies distributing free software will individually obtain patent licenses, thus in effect transforming the program into proprietary software. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. - Most GNU software, including some libraries, is covered by the ordinary +Most GNU software, including some libraries, is covered by the ordinary GNU General Public License, which was designed for utility programs. This license, the GNU Library General Public License, applies to certain designated libraries. This license is quite different from the ordinary one; be sure to read it in full, and don't assume that anything in it is the same as in the ordinary license. - The reason we have a separate public license for some libraries is that +The reason we have a separate public license for some libraries is that they blur the distinction we usually make between modifying or adding to a program and simply using it. Linking a program with a library, without changing the library, is in some sense simply using the library, and is @@ -44385,12 +44594,12 @@ a textual and legal sense, the linked executable is a combined work, a derivative of the original library, and the ordinary General Public License treats it as such. - Because of this blurred distinction, using the ordinary General +Because of this blurred distinction, using the ordinary General Public License for libraries did not effectively promote software sharing, because most developers did not use the libraries. We concluded that weaker conditions might promote sharing better. - However, unrestricted linking of non-free programs would deprive the +However, unrestricted linking of non-free programs would deprive the users of those programs of all benefit from the free status of the libraries themselves. This Library General Public License is intended to permit developers of non-free programs to use free libraries, while @@ -44400,29 +44609,29 @@ this as regards changes in header files, but we have achieved it as regards changes in the actual functions of the Library.) The hope is that this will lead to faster development of free libraries. - The precise terms and conditions for copying, distribution and +The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, while the latter only works together with the library. - Note that it is possible for a library to be covered by the ordinary +Note that it is possible for a library to be covered by the ordinary General Public License rather than by this special one. - GNU LIBRARY GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + GNU LIBRARY GENERAL PUBLIC LICENSE +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - 0. This License Agreement applies to any software library which +0. This License Agreement applies to any software library which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Library General Public License (also called "this License"). Each licensee is addressed as "you". - A "library" means a collection of software functions and/or data +A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. - The "Library", below, refers to any such software library or work +The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a @@ -44430,13 +44639,13 @@ portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) - "Source code" for a work means the preferred form of the work for +"Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. - Activities other than copying, distribution and modification are not +Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based @@ -44444,7 +44653,7 @@ on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. - 1. You may copy and distribute verbatim copies of the Library's +1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact @@ -44452,37 +44661,37 @@ all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. - You may charge a fee for the physical act of transferring a copy, +You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. - 2. You may modify your copy or copies of the Library or any portion +2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: - a) The modified work must itself be a software library. +a) The modified work must itself be a software library. - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. +b) You must cause the files modified to carry prominent notices +stating that you changed the files and the date of any change. - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. +c) You must cause the whole of the work to be licensed at no +charge to all third parties under the terms of this License. - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. +d) If a facility in the modified Library refers to a function or a +table of data to be supplied by an application program that uses +the facility, other than as an argument passed when the facility +is invoked, then you must make a good faith effort to ensure that, +in the event an application does not supply such function or +table, the facility still operates, and performs whatever part of +its purpose remains meaningful. - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) +(For example, a function in a library to compute square roots has +a purpose that is entirely well-defined independent of the +application. Therefore, Subsection 2d requires that any +application-supplied function or table used by this function must +be optional: if the application does not supply it, the square +root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, @@ -44505,7 +44714,7 @@ with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. - 3. You may opt to apply the terms of the ordinary GNU General Public +3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, @@ -44514,65 +44723,65 @@ ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. - Once this change is made in a given copy, it is irreversible for +Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. - This option is useful when you wish to copy part of the code of +This option is useful when you wish to copy part of the code of the Library into a program that is not a library. - 4. You may copy and distribute the Library (or a portion or +4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. - If distribution of object code is made by offering access to copy +If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. - 5. A program that contains no derivative of any portion of the +5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. - However, linking a "work that uses the Library" with the Library +However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. - When a "work that uses the Library" uses material from a header file +When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. - If such an object file uses only numerical parameters, data +If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) - Otherwise, if the work is a derivative of the Library, you may +Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. - 6. As an exception to the Sections above, you may also compile or +6. As an exception to the Sections above, you may also compile or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. - You must give prominent notice with each copy of the work that the +You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the @@ -44580,31 +44789,31 @@ copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - c) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - d) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the +a) Accompany the work with the complete corresponding +machine-readable source code for the Library including whatever +changes were used in the work (which must be distributed under +Sections 1 and 2 above); and, if the work is an executable linked +with the Library, with the complete machine-readable "work that +uses the Library", as object code and/or source code, so that the +user can modify the Library and then relink to produce a modified +executable containing the modified Library. (It is understood +that the user who changes the contents of definitions files in the +Library will not necessarily be able to recompile the application +to use the modified definitions.) + +b) Accompany the work with a written offer, valid for at +least three years, to give the same user the materials +specified in Subsection 6a, above, for a charge no more +than the cost of performing this distribution. + +c) If distribution of the work is made by offering access to copy +from a designated place, offer equivalent access to copy the above +specified materials from the same place. + +d) Verify that the user has already received a copy of these +materials or that you have already sent this user a copy. + +For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the source code distributed need not include anything that is normally @@ -44613,29 +44822,29 @@ components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. - It may happen that this requirement contradicts the license +It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. - 7. You may place library facilities that are a work based on the +7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. +a) Accompany the combined library with a copy of the same work +based on the Library, uncombined with any other library +facilities. This must be distributed under the terms of the +Sections above. - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. +b) Give prominent notice with the combined library of the fact +that part of it is a work based on the Library, and explaining +where to find the accompanying uncombined form of the same work. - 8. You may not copy, modify, sublicense, link with, or distribute +8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your @@ -44643,7 +44852,7 @@ rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. - 9. You are not required to accept this License, since you have not +9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by @@ -44652,7 +44861,7 @@ Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. - 10. Each time you redistribute the Library (or any work based on the +10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further @@ -44660,7 +44869,7 @@ restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. - 11. If, as a consequence of a court judgment or allegation of patent +11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not @@ -44691,7 +44900,7 @@ impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. - 12. If the distribution and/or use of the Library is restricted in +12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, @@ -44699,7 +44908,7 @@ so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. - 13. The Free Software Foundation may publish revised and/or new +13. The Free Software Foundation may publish revised and/or new versions of the Library General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. @@ -44712,7 +44921,7 @@ the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. - 14. If you wish to incorporate parts of the Library into other free +14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free @@ -44721,9 +44930,9 @@ decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. - NO WARRANTY + NO WARRANTY - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY @@ -44733,7 +44942,7 @@ PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR @@ -44744,37 +44953,37 @@ FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - END OF TERMS AND CONDITIONS + END OF TERMS AND CONDITIONS - Appendix: How to Apply These Terms to Your New Libraries +Appendix: How to Apply These Terms to Your New Libraries - If you develop a new library, and you want it to be of the greatest +If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). - To apply these terms, attach the following notices to the library. It is +To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. - <one line to give the library's name and a brief idea of what it does.> - Copyright (C) <year> <name of author> +<one line to give the library's name and a brief idea of what it does.> +Copyright (C) <year> <name of author> - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free +Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Also add information on how to contact you by electronic and paper mail. @@ -44782,11 +44991,11 @@ You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James Random Hacker. +Yoyodyne, Inc., hereby disclaims all copyright interest in the +library `Frob' (a library for tweaking knobs) written by James Random Hacker. - <signature of Ty Coon>, 1 April 1990 - Ty Coon, President of Vice +<signature of Ty Coon>, 1 April 1990 +Ty Coon, President of Vice That's all there is to it! @end example diff --git a/client/mysql.cc b/client/mysql.cc index 8adb65ab3a6..5494ee6ccb9 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -115,7 +115,7 @@ static bool info_flag=0,ignore_errors=0,wait_flag=0,quick=0, opt_compress=0, vertical=0,skip_line_numbers=0,skip_column_names=0,opt_html=0, no_named_cmds=1; // we want this to be the default -static uint verbose=0,opt_silent=0,opt_mysql_port=0; +static uint verbose=0,opt_silent=0,opt_mysql_port=0,opt_connect_timeout=0; static my_string opt_mysql_unix_port=0; static int connect_flag=CLIENT_INTERACTIVE; static char *current_host,*current_db,*current_user=0,*opt_password=0, @@ -334,7 +334,7 @@ sig_handler mysql_end(int sig) exit(status.exit_status); } -enum options {OPT_CHARSETS_DIR=256, OPT_DEFAULT_CHARSET} ; +enum options {OPT_CHARSETS_DIR=256, OPT_DEFAULT_CHARSET, OPT_TIMEOUT} ; static struct option long_options[] = @@ -374,6 +374,7 @@ static struct option long_options[] = {"socket", required_argument, 0, 'S'}, #include "sslopt-longopts.h" {"table", no_argument, 0, 't'}, + {"timeout", required_argument, 0, OPT_TIMEOUT}, #ifndef DONT_ALLOW_USER_CHANGE {"user", required_argument, 0, 'u'}, #endif @@ -545,9 +546,12 @@ static int get_options(int argc, char **argv) case 'p': if (optarg) { + char *start=optarg; my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR)); opt_password=my_strdup(optarg,MYF(MY_FAE)); while (*optarg) *optarg++= 'x'; // Destroy argument + if (*start) + start[1]=0; } else tty_password=1; @@ -603,6 +607,9 @@ static int get_options(int argc, char **argv) opt_mysql_unix_port=my_strdup(MYSQL_NAMEDPIPE,MYF(0)); #endif break; + case OPT_TIMEOUT: + opt_connect_timeout=atoi(optarg); + break; case 'V': usage(1); exit(0); case 'I': case '?': @@ -1772,6 +1779,9 @@ sql_real_connect(char *host,char *database,char *user,char *password, connected= 0; } mysql_init(&mysql); + if (opt_connect_timeout) + mysql_options(&mysql,MYSQL_OPT_CONNECT_TIMEOUT, + (char*) &opt_connect_timeout); if (opt_compress) mysql_options(&mysql,MYSQL_OPT_COMPRESS,NullS); #ifdef HAVE_OPENSSL diff --git a/client/mysqladmin.c b/client/mysqladmin.c index f8432ec7fb6..d5b2e73451e 100644 --- a/client/mysqladmin.c +++ b/client/mysqladmin.c @@ -28,7 +28,7 @@ #include <my_pthread.h> /* because of signal() */ #endif -#define ADMIN_VERSION "8.9" +#define ADMIN_VERSION "8.11" #define MAX_MYSQL_VAR 64 #define MAX_TIME_TO_WAIT 3600 /* Wait for shutdown */ #define MAX_TRUNC_LENGTH 3 @@ -137,7 +137,7 @@ int main(int argc,char *argv[]) { int c, error = 0,option_index=0; MYSQL mysql; - char *host = NULL,*password=0,*user=0,**commands; + char *host = NULL,*opt_password=0,*user=0,**commands; my_bool tty_password=0; MY_INIT(argv[0]); mysql_init(&mysql); @@ -160,9 +160,12 @@ int main(int argc,char *argv[]) case 'p': if (optarg) { - my_free(password,MYF(MY_ALLOW_ZERO_PTR)); - password=my_strdup(optarg,MYF(MY_FAE)); + char *start=optarg; + my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR)); + opt_password=my_strdup(optarg,MYF(MY_FAE)); while (*optarg) *optarg++= 'x'; /* Destroy argument */ + if (*start) + start[1]=0; /* Cut length of argument */ } else tty_password=1; @@ -243,12 +246,11 @@ int main(int argc,char *argv[]) exit(1); } if (tty_password) - password = get_tty_password(NullS); + opt_password = get_tty_password(NullS); VOID(signal(SIGINT,endprog)); /* Here if abort */ VOID(signal(SIGTERM,endprog)); /* Here if abort */ - mysql_init(&mysql); if (opt_compress) mysql_options(&mysql,MYSQL_OPT_COMPRESS,NullS); #ifdef HAVE_OPENSSL @@ -256,7 +258,7 @@ int main(int argc,char *argv[]) mysql_ssl_set(&mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca, opt_ssl_capath); #endif /* HAVE_OPENSSL */ - if (sql_connect(&mysql,host,user,password,option_wait)) + if (sql_connect(&mysql,host,user,opt_password,option_wait)) error = 1; else { @@ -269,7 +271,7 @@ int main(int argc,char *argv[]) if (option_wait && !interrupted) { mysql_close(&mysql); - if (!sql_connect(&mysql,host,user,password,option_wait)) + if (!sql_connect(&mysql,host,user,opt_password,option_wait)) continue; /* Retry */ } error=1; @@ -286,7 +288,7 @@ int main(int argc,char *argv[]) } mysql_close(&mysql); } - my_free(password,MYF(MY_ALLOW_ZERO_PTR)); + my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR)); my_free(user,MYF(MY_ALLOW_ZERO_PTR)); free_defaults(argv); my_end(0); diff --git a/client/mysqldump.c b/client/mysqldump.c index b1c77b209aa..019069d81b0 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -37,7 +37,7 @@ ** Tõnu Samuel <tonu@please.do.not.remove.this.spam.ee> **/ -#define DUMP_VERSION "8.10" +#define DUMP_VERSION "8.11" #include <global.h> #include <my_sys.h> @@ -75,7 +75,7 @@ static my_bool verbose=0,tFlag=0,cFlag=0,dFlag=0,quick=0, extended_insert = 0, opt_delayed=0,create_options=0,opt_quoted=0,opt_databases=0, opt_alldbs=0,opt_create_db=0,opt_first_slave=0; static MYSQL mysql_connection,*sock=0; -static char insert_pat[12 * 1024],*password=0,*current_user=0, +static char insert_pat[12 * 1024],*opt_password=0,*current_user=0, *current_host=0,*path=0,*fields_terminated=0, *lines_terminated=0, *enclosed=0, *opt_enclosed=0, *escaped=0, *where=0, *default_charset; @@ -333,9 +333,12 @@ static int get_options(int *argc,char ***argv) case 'p': if (optarg) { - my_free(password,MYF(MY_ALLOW_ZERO_PTR)); - password=my_strdup(optarg,MYF(MY_FAE)); - while (*optarg) *optarg++= 'x'; /* Destroy argument */ + char *start=optarg; + my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR)); + opt_password=my_strdup(optarg,MYF(MY_FAE)); + while (*optarg) *optarg++= 'x'; /* Destroy argument */ + if (*start) + start[1]=0; /* Cut length of argument */ } else tty_password=1; @@ -459,7 +462,7 @@ static int get_options(int *argc,char ***argv) return 1; } if (tty_password) - password=get_tty_password(NullS); + opt_password=get_tty_password(NullS); return(0); } /* get_options */ @@ -596,7 +599,6 @@ static uint getTableStructure(char *table, char* db) sprintf(insert_pat,"SET OPTION SQL_QUOTE_SHOW_CREATE=%d", opt_quoted); table_name=quote_name(table,table_buff); - if (mysql_query(sock,insert_pat)) { /* using SHOW CREATE statement */ @@ -1318,7 +1320,7 @@ int main(int argc, char **argv) my_end(0); exit(EX_USAGE); } - if (dbConnect(current_host, current_user, password)) + if (dbConnect(current_host, current_user, opt_password)) exit(EX_MYSQLERR); if (!path) write_heder(stdout, *argv); @@ -1358,7 +1360,7 @@ int main(int argc, char **argv) } dbDisconnect(current_host); puts(""); - my_free(password, MYF(MY_ALLOW_ZERO_PTR)); + my_free(opt_password, MYF(MY_ALLOW_ZERO_PTR)); if (extended_insert) dynstr_free(&extended_row); my_end(0); diff --git a/client/mysqlimport.c b/client/mysqlimport.c index 596b68591b7..d00c99d4061 100644 --- a/client/mysqlimport.c +++ b/client/mysqlimport.c @@ -25,7 +25,7 @@ ** * * ** ************************* */ -#define IMPORT_VERSION "2.4" +#define IMPORT_VERSION "2.6" #include <global.h> #include <my_sys.h> @@ -45,7 +45,7 @@ static my_bool verbose=0,lock_tables=0,ignore_errors=0,delete=0, replace=0,silent=0,ignore=0,opt_compress=0,opt_local_file=0; static MYSQL mysql_connection; -static char *password=0, *current_user=0, +static char *opt_password=0, *current_user=0, *current_host=0, *current_db=0, *fields_terminated=0, *lines_terminated=0, *enclosed=0, *opt_enclosed=0, *escaped=0, opt_low_priority=0, *opt_columns=0; @@ -125,7 +125,7 @@ file. The SQL command 'LOAD DATA INFILE' is used to import the rows.\n"); Give the column names in a comma separated list.\n\ This is same as giving columns to LOAD DATA INFILE.\n\ -C, --compress Use compression in server/client protocol\n\ - -d, --delete Deletes first all rows from table.\n\ + -d, --delete First delete all rows from table.\n\ -f, --force Continue even if we get an sql-error.\n\ -h, --host=... Connect to host.\n\ -i, --ignore If duplicate unique key was found, keep old row.\n\ @@ -202,9 +202,12 @@ static int get_options(int *argc, char ***argv) case 'p': if (optarg) { - my_free(password,MYF(MY_ALLOW_ZERO_PTR)); - password= my_strdup(optarg,MYF(MY_FAE)); + char *start=optarg; + my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR)); + opt_password=my_strdup(optarg,MYF(MY_FAE)); while (*optarg) *optarg++= 'x'; /* Destroy argument */ + if (*start) + start[1]=0; /* Cut length of argument */ } else tty_password= 1; @@ -276,7 +279,7 @@ static int get_options(int *argc, char ***argv) current_db= *((*argv)++); (*argc)--; if (tty_password) - password=get_tty_password(NullS); + opt_password=get_tty_password(NullS); return(0); } @@ -504,7 +507,7 @@ int main(int argc, char **argv) argv_to_free= argv; if (get_options(&argc, &argv)) return(1); - if (!(sock= db_connect(current_host,current_db,current_user,password))) + if (!(sock= db_connect(current_host,current_db,current_user,opt_password))) return(1); /* purecov: deadcode */ if (lock_tables) lock_table(sock, argc, argv); @@ -513,7 +516,7 @@ int main(int argc, char **argv) if (exitcode == 0) exitcode = error; db_disconnect(current_host, sock); - my_free(password,MYF(MY_ALLOW_ZERO_PTR)); + my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR)); free_defaults(argv_to_free); my_end(0); return(exitcode); diff --git a/client/mysqlshow.c b/client/mysqlshow.c index bf924ddeecd..3c34b2df4b5 100644 --- a/client/mysqlshow.c +++ b/client/mysqlshow.c @@ -28,7 +28,7 @@ #include <stdarg.h> #include <getopt.h> -static my_string host=0,password=0,user=0; +static my_string host=0,opt_password=0,user=0; static my_bool opt_show_keys=0,opt_compress=0,opt_status=0; static void get_options(int *argc,char ***argv); @@ -88,15 +88,13 @@ int main(int argc, char **argv) mysql_ssl_set(&mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca, opt_ssl_capath); #endif - if (!(mysql_real_connect(&mysql,host,user,password, + if (!(mysql_real_connect(&mysql,host,user,opt_password, argv[0],opt_mysql_port,opt_mysql_unix_port, 0))) { fprintf(stderr,"%s: %s\n",my_progname,mysql_error(&mysql)); exit(1); } - /* if (!(mysql_connect(&mysql,host,user,password))) */ - switch (argc) { @@ -111,11 +109,12 @@ int main(int argc, char **argv) if (opt_status && ! wild) error=list_table_status(&mysql,argv[0],argv[1]); else - error=list_fields(&mysql,argv[0],argv[1],wild); break; + error=list_fields(&mysql,argv[0],argv[1],wild); + break; } mysql_close(&mysql); /* Close & free connection */ - if (password) - my_free(password,MYF(0)); + if (opt_password) + my_free(opt_password,MYF(0)); my_end(0); exit(error ? 1 : 0); return 0; /* No compiler warnings */ @@ -223,9 +222,12 @@ get_options(int *argc,char ***argv) case 'p': if (optarg) { - my_free(password,MYF(MY_ALLOW_ZERO_PTR)); - password=my_strdup(optarg,MYF(MY_FAE)); + char *start=optarg; + my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR)); + opt_password=my_strdup(optarg,MYF(MY_FAE)); while (*optarg) *optarg++= 'x'; /* Destroy argument */ + if (*start) + start[1]=0; /* Cut length of argument */ } else tty_password=1; @@ -266,7 +268,7 @@ get_options(int *argc,char ***argv) (*argc)-=optind; (*argv)+=optind; if (tty_password) - password=get_tty_password(NullS); + opt_password=get_tty_password(NullS); return; } diff --git a/client/sql_string.cc b/client/sql_string.cc index 7ca2d3c419e..4b9ebef21f1 100644 --- a/client/sql_string.cc +++ b/client/sql_string.cc @@ -95,17 +95,6 @@ bool String::realloc(uint32 alloc_length) return FALSE; } - -#ifdef NOT_NEEDED -bool String::set(long num) -{ - if (alloc(14)) - return TRUE; - str_length=(uint32) (int10_to_str(num,Ptr,-10)-Ptr); - return FALSE; -} -#endif - bool String::set(longlong num) { if (alloc(21)) @@ -274,6 +263,7 @@ bool String::append(const char *s,uint32 arg_length) return FALSE; } +#ifdef TO_BE_REMOVED bool String::append(FILE* file, uint32 arg_length, myf my_flags) { if (realloc(str_length+arg_length)) @@ -286,6 +276,20 @@ bool String::append(FILE* file, uint32 arg_length, myf my_flags) str_length+=arg_length; return FALSE; } +#endif + +bool String::append(IO_CACHE* file, uint32 arg_length) +{ + if (realloc(str_length+arg_length)) + return TRUE; + if (my_b_read(file, (byte*) Ptr + str_length, arg_length)) + { + shrink(str_length); + return TRUE; + } + str_length+=arg_length; + return FALSE; +} uint32 String::numchars() { diff --git a/client/sql_string.h b/client/sql_string.h index 8711cf314ad..74dbc4cc6bd 100644 --- a/client/sql_string.h +++ b/client/sql_string.h @@ -100,16 +100,16 @@ public: bool set(ulonglong num); bool set(double num,uint decimals=2); inline void free() + { + if (alloced) { - if (alloced) - { - alloced=0; - Alloced_length=0; - my_free(Ptr,MYF(0)); - Ptr=0; - } + alloced=0; + Alloced_length=0; + my_free(Ptr,MYF(0)); + Ptr=0; + str_length=0; /* Safety */ } - + } inline bool alloc(uint32 arg_length) { if (arg_length < Alloced_length) @@ -152,7 +152,7 @@ public: bool copy(const char *s,uint32 arg_length); // Allocate new string bool append(const String &s); bool append(const char *s,uint32 arg_length=0); - bool append(FILE* file, uint32 arg_length, myf my_flags); + bool append(IO_CACHE* file, uint32 arg_length); int strstr(const String &search,uint32 offset=0); // Returns offset to substring or -1 int strrstr(const String &search,uint32 offset=0); // Returns offset to substring or -1 bool replace(uint32 offset,uint32 arg_length,const String &to); diff --git a/configure.in b/configure.in index 4a8b5dbfa4c..6811404bc35 100644 --- a/configure.in +++ b/configure.in @@ -4,7 +4,7 @@ dnl Process this file with autoconf to produce a configure script. AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # The Docs Makefile.am parses this line! -AM_INIT_AUTOMAKE(mysql, 3.23.27-beta) +AM_INIT_AUTOMAKE(mysql, 3.23.28-gamma) AM_CONFIG_HEADER(config.h) PROTOCOL_VERSION=10 @@ -687,6 +687,8 @@ case $SYSTEM_TYPE in then CFLAGS="$CFLAGS -traditional-cpp -DHAVE_DARWIN_THREADS" CXXFLAGS="$CXXFLAGS -traditional-cpp -DHAVE_DARWIN_THREADS" + CFLAGS="$CFLAGS -traditional-cpp -DHAVE_DARWIN_THREADS -D_P1003_1B_VISIBLE" + CXXFLAGS="$CXXFLAGS -traditional-cpp -DHAVE_DARWIN_THREADS -D_P1003_1B_VISIBLE" MAX_C_OPTIMIZE="-O" with_named_curses="" fi @@ -1235,13 +1237,13 @@ AC_FUNC_UTIME_NULL AC_FUNC_VPRINTF AC_CHECK_FUNCS(alarm bmove \ chsize ftruncate rint finite fpsetmask fpresetsticky\ - cuserid fcntl fconvert \ + cuserid fcntl fconvert poll \ getrusage getpwuid getcwd getrlimit getwd index stpcpy locking longjmp \ perror pread realpath rename \ socket strnlen madvise mkstemp \ strtol strtoul strtoull snprintf tempnam thr_setconcurrency \ gethostbyaddr_r gethostbyname_r getpwnam \ - bfill bzero bcmp strstr strpbrk strerror\ + bfill bzero bcmp strstr strpbrk strerror \ tell atod memcpy memmove \ setupterm strcasecmp sighold \ vidattr setupterm lrand48 localtime_r \ diff --git a/include/my_pthread.h b/include/my_pthread.h index bef7da93451..c7b5831a474 100644 --- a/include/my_pthread.h +++ b/include/my_pthread.h @@ -351,10 +351,9 @@ struct tm *localtime_r(const time_t *clock, struct tm *res); #define pthread_kill(A,B) pthread_dummy(0) #define pthread_condattr_init(A) pthread_dummy(0) #define pthread_condattr_destroy(A) pthread_dummy(0) -#define pthread_cond_init( A, B ) pthread_cond_init( (A), 0 ) #define pthread_signal(A,B) pthread_dummy(0) #undef pthread_detach_this_thread -#define pthread_detach_this_thread() { pthread_t tmp=pthread_self() ; pthread_detach(&tmp); } +#define pthread_detach_this_thread() { pthread_t tmp=pthread_self() ; pthread_detach(tmp); } #undef sigset #define sigset(A,B) pthread_signal((A),(void (*)(int)) (B)) #endif diff --git a/include/my_sys.h b/include/my_sys.h index 3fc4fed3397..32b2d18fb4d 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -59,6 +59,7 @@ extern int NEAR my_errno; /* Last error in mysys */ #define MY_WME 16 /* Write message on error */ #define MY_WAIT_IF_FULL 32 /* Wait and try again if disk full error */ #define MY_RAID 64 /* Support for RAID (not the "Johnson&Johnson"-s one ;) */ +#define MY_DONT_CHECK_FILESIZE 128 /* Option to init_io_cache() */ #define MY_LINK_WARNING 32 /* my_redel() gives warning if links */ #define MY_COPYTIME 64 /* my_redel() copys time */ #define MY_HOLD_ORIGINAL_MODES 128 /* my_copy() holds to file modes */ @@ -506,6 +507,10 @@ extern int my_block_write(IO_CACHE *info, const byte *Buffer, uint Count, my_off_t pos); extern int flush_io_cache(IO_CACHE *info); extern int end_io_cache(IO_CACHE *info); +extern uint my_b_fill(IO_CACHE *info); +extern void my_b_seek(IO_CACHE *info,my_off_t pos); +extern uint my_b_gets(IO_CACHE *info, char *to, uint max_length); +extern uint my_b_printf(IO_CACHE *info, const char* fmt, ...); extern my_bool open_cached_file(IO_CACHE *cache,const char *dir, const char *prefix, uint cache_size, myf cache_myflags); diff --git a/include/violite.h b/include/violite.h index e7c3e8ede81..1f44c29ba65 100644 --- a/include/violite.h +++ b/include/violite.h @@ -108,6 +108,9 @@ my_bool vio_peer_addr(Vio * vio, char *buf); void vio_in_addr(Vio *vio, struct in_addr *in); + /* Return 1 if there is data to be read */ +my_bool vio_poll_read(Vio *vio,uint timeout); + #ifdef __cplusplus } #endif diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index c7820916c97..5cdbf12dfc4 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -64,6 +64,12 @@ my_string mysql_unix_port=0; #define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | CLIENT_LOCAL_FILES | CLIENT_TRANSACTIONS) +#ifdef __WIN__ +#define CONNECT_TIMEOUT 20 +#else +#define CONNECT_TIMEOUT 0 +#endif + #if defined(MSDOS) || defined(__WIN__) #define ERRNO WSAGetLastError() #define perror(A) @@ -113,7 +119,7 @@ static ulong mysql_sub_escape_string(CHARSET_INFO *charset_info, char *to, *****************************************************************************/ static int connect2(my_socket s, const struct sockaddr *name, uint namelen, - uint to) + uint timeout) { #if defined(__WIN__) return connect(s, (struct sockaddr*) name, namelen); @@ -128,7 +134,7 @@ static int connect2(my_socket s, const struct sockaddr *name, uint namelen, * exactly like the normal connect() call does. */ - if (to == 0) + if (timeout == 0) return connect(s, (struct sockaddr*) name, namelen); flags = fcntl(s, F_GETFL, 0); /* Set socket to not block */ @@ -175,13 +181,13 @@ static int connect2(my_socket s, const struct sockaddr *name, uint namelen, start_time = time(NULL); for (;;) { - tv.tv_sec = (long) to; + tv.tv_sec = (long) timeout; tv.tv_usec = 0; if ((res = select(s+1, NULL, &sfds, NULL, &tv)) >= 0) break; now_time=time(NULL); - to-= (uint) (now_time - start_time); - if (errno != EINTR || (int) to <= 0) + timeout-= (uint) (now_time - start_time); + if (errno != EINTR || (int) timeout <= 0) return -1; } @@ -195,7 +201,7 @@ static int connect2(my_socket s, const struct sockaddr *name, uint namelen, return(-1); if (s_err) - { /* getsockopt() could suceed */ + { /* getsockopt could succeed */ errno = s_err; return(-1); /* but return an error... */ } @@ -1001,9 +1007,7 @@ mysql_init(MYSQL *mysql) } else bzero((char*) (mysql),sizeof(*(mysql))); -#ifdef __WIN__ - mysql->options.connect_timeout=20; -#endif + mysql->options.connect_timeout=CONNECT_TIMEOUT; #if defined(SIGPIPE) && defined(THREAD) if (!((mysql)->client_flag & CLIENT_IGNORE_SIGPIPE)) (void) signal(SIGPIPE,pipe_sig_handler); @@ -1140,7 +1144,8 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, const char *passwd, const char *db, uint port, const char *unix_socket,uint client_flag) { - char buff[100],charset_name_buff[16],*end,*host_info, *charset_name; + char buff[NAME_LEN+100],charset_name_buff[16],*end,*host_info, + *charset_name; my_socket sock; uint32 ip_addr; struct sockaddr_in sock_addr; @@ -1342,6 +1347,13 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, /* Get version info */ mysql->protocol_version= PROTOCOL_VERSION; /* Assume this */ + if (mysql->options.connect_timeout && + vio_poll_read(net->vio, mysql->options.connect_timeout)) + { + net->last_errno= CR_SERVER_LOST; + strmov(net->last_error,ER(net->last_errno)); + goto error; + } if ((pkt_length=net_safe_read(mysql)) == packet_error) goto error; @@ -1497,7 +1509,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, int3store(buff+2,max_allowed_packet); if (user && user[0]) - strmake(buff+5,user,32); + strmake(buff+5,user,32); /* Max user name */ else read_user_name((char*) buff+5); #ifdef _CUSTOMCONFIG_ @@ -1508,7 +1520,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, (my_bool) (mysql->protocol_version == 9)); if (db && (mysql->server_capabilities & CLIENT_CONNECT_WITH_DB)) { - end=strmov(end+1,db); + end=strmake(end+1,db,NAME_LEN); mysql->db=my_strdup(db,MYF(MY_WME)); db=0; } diff --git a/libmysql/violite.c b/libmysql/violite.c index 349a6fbd849..4efda9f3b90 100644 --- a/libmysql/violite.c +++ b/libmysql/violite.c @@ -32,6 +32,9 @@ #include <my_sys.h> #include <my_net.h> #include <m_string.h> +#ifdef HAVE_POLL +#include <sys/poll.h> +#endif #if defined(__EMX__) #include <sys/ioctl.h> @@ -98,7 +101,9 @@ Vio *vio_new(my_socket sd, enum enum_vio_type type, my_bool localhost) if ((vio = (Vio*) my_malloc(sizeof(*vio),MYF(MY_WME)))) { vio_reset(vio, type, sd, 0, localhost); - sprintf(vio->desc, "socket (%d)", vio->sd); + sprintf(vio->desc, + (vio->type == VIO_TYPE_SOCKET ? "socket (%d)" : "TCP/IP (%d)"), + vio->sd); #if !defined(___WIN__) && !defined(__EMX__) #if !defined(NO_FCNTL_NONBLOCK) vio->fcntl_mode = fcntl(sd, F_GETFL); @@ -261,7 +266,7 @@ vio_is_blocking(Vio * vio) } -int vio_fastsend(Vio * vio, my_bool onoff) +int vio_fastsend(Vio * vio __attribute__((unused)), my_bool onoff) { int r=0; DBUG_ENTER("vio_fastsend"); @@ -322,7 +327,7 @@ int vio_close(Vio * vio) if (vio->type == VIO_TYPE_NAMEDPIPE) { #if defined(__NT__) && defined(MYSQL_SERVER) - CancelIO(vio->hPipe); + CancelIo(vio->hPipe); DisconnectNamedPipe(vio->hPipe); #endif r=CloseHandle(vio->hPipe); @@ -397,4 +402,26 @@ void vio_in_addr(Vio *vio, struct in_addr *in) DBUG_VOID_RETURN; } + +/* Return 0 if there is data to be read */ + +my_bool vio_poll_read(Vio *vio,uint timeout) +{ +#ifndef HAVE_POLL + return 0; +#else + struct pollfd fds; + int res; + DBUG_ENTER("vio_poll"); + fds.fd=vio->sd; + fds.events=POLLIN; + fds.revents=0; + if ((res=poll(&fds,1,(int) timeout*1000)) <= 0) + { + DBUG_RETURN(res < 0 ? 0 : 1); /* Don't return 1 on errors */ + } + DBUG_RETURN(fds.revents & POLLIN ? 0 : 1); +#endif +} + #endif /* HAVE_VIO */ diff --git a/mysql.proj b/mysql.proj Binary files differindex ed591da265e..a6e5d9c5852 100644 --- a/mysql.proj +++ b/mysql.proj diff --git a/mysys/Makefile.am b/mysys/Makefile.am index 6b38d9364f6..3d60716e358 100644 --- a/mysys/Makefile.am +++ b/mysys/Makefile.am @@ -26,7 +26,7 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c\ mf_path.c mf_loadpath.c\ my_open.c my_create.c my_seek.c my_read.c \ my_pread.c my_write.c \ - mf_reccache.c mf_keycache.c \ + mf_keycache.c \ mf_iocache.c mf_cache.c mf_tempfile.c \ my_lock.c mf_brkhant.c my_alarm.c \ my_malloc.c my_realloc.c my_once.c mulalloc.c \ diff --git a/mysys/hash.c b/mysys/hash.c index a6181443a42..9c6497c7717 100644 --- a/mysys/hash.c +++ b/mysys/hash.c @@ -374,10 +374,11 @@ my_bool hash_delete(HASH *hash,byte *record) uint blength,pos2,pos_hashnr,lastpos_hashnr,idx,empty_index; HASH_LINK *data,*lastpos,*gpos,*pos,*pos3,*empty; DBUG_ENTER("hash_delete"); + if (!hash->records) + DBUG_RETURN(1); blength=hash->blength; data=dynamic_element(&hash->array,0,HASH_LINK*); - /* Search after record with key */ pos=data+ hash_mask(rec_hashnr(hash,record),blength,hash->records); gpos = 0; diff --git a/mysys/mf_cache.c b/mysys/mf_cache.c index 2c197f6fd20..ff29926ac50 100644 --- a/mysys/mf_cache.c +++ b/mysys/mf_cache.c @@ -74,7 +74,7 @@ my_bool open_cached_file(IO_CACHE *cache, const char* dir, const char *prefix, } my_free(cache->dir, MYF(MY_ALLOW_ZERO_PTR)); my_free(cache->prefix,MYF(MY_ALLOW_ZERO_PTR)); - DBUG_RETURN(0); + DBUG_RETURN(1); } /* Create the temporary file */ @@ -101,10 +101,12 @@ void close_cached_file(IO_CACHE *cache) DBUG_ENTER("close_cached_file"); if (my_b_inited(cache)) { + File file=cache->file; + cache->file= -1; /* Don't flush data */ (void) end_io_cache(cache); - if (cache->file >= 0) + if (file >= 0) { - (void) my_close(cache->file,MYF(0)); + (void) my_close(file,MYF(0)); #ifdef CANT_DELETE_OPEN_FILES if (cache->file_name) { diff --git a/mysys/mf_iocache.c b/mysys/mf_iocache.c index 86cf5fc65e2..0d1c227c2b2 100644 --- a/mysys/mf_iocache.c +++ b/mysys/mf_iocache.c @@ -22,10 +22,13 @@ (and get a EOF-error). Possibly use of asyncronic io. macros for read and writes for faster io. - Used instead of FILE when reading or writing hole files. - This shall make mf_rec_cache obsolite. - One can change info->pos_in_file to a higer value to skipp bytes in file if + Used instead of FILE when reading or writing whole files. + This will make mf_rec_cache obsolete. + One can change info->pos_in_file to a higher value to skip bytes in file if also info->rc_pos is set to info->rc_end. + If called through open_cached_file(), then the temporary file will + only be created if a write exeeds the file buffer or if one calls + flush_io_cache(). */ #define MAP_TO_USE_RAID @@ -40,7 +43,7 @@ static void my_aiowait(my_aio_result *result); /* ** if cachesize == 0 then use default cachesize (from s-file) - ** if file == -1 then real_open_cached_file() will be called to + ** if file == -1 then real_open_cached_file() will be called. ** returns 0 if ok */ @@ -59,17 +62,24 @@ int init_io_cache(IO_CACHE *info, File file, uint cachesize, min_cache=use_async_io ? IO_SIZE*4 : IO_SIZE*2; if (type == READ_CACHE) { /* Assume file isn't growing */ - my_off_t file_pos,end_of_file; - if ((file_pos=my_tell(file,MYF(0)) == MY_FILEPOS_ERROR)) - DBUG_RETURN(1); - end_of_file=my_seek(file,0L,MY_SEEK_END,MYF(0)); - if (end_of_file < seek_offset) - end_of_file=seek_offset; - VOID(my_seek(file,file_pos,MY_SEEK_SET,MYF(0))); - if ((my_off_t) cachesize > end_of_file-seek_offset+IO_SIZE*2-1) + if (cache_myflags & MY_DONT_CHECK_FILESIZE) { - cachesize=(uint) (end_of_file-seek_offset)+IO_SIZE*2-1; - use_async_io=0; /* No nead to use async */ + cache_myflags &= ~MY_DONT_CHECK_FILESIZE; + } + else + { + my_off_t file_pos,end_of_file; + if ((file_pos=my_tell(file,MYF(0)) == MY_FILEPOS_ERROR)) + DBUG_RETURN(1); + end_of_file=my_seek(file,0L,MY_SEEK_END,MYF(0)); + if (end_of_file < seek_offset) + end_of_file=seek_offset; + VOID(my_seek(file,file_pos,MY_SEEK_SET,MYF(0))); + if ((my_off_t) cachesize > end_of_file-seek_offset+IO_SIZE*2-1) + { + cachesize=(uint) (end_of_file-seek_offset)+IO_SIZE*2-1; + use_async_io=0; /* No nead to use async */ + } } } @@ -545,7 +555,6 @@ int my_block_write(register IO_CACHE *info, const byte *Buffer, uint Count, return error; } - /* Flush write cache */ int flush_io_cache(IO_CACHE *info) @@ -565,7 +574,9 @@ int flush_io_cache(IO_CACHE *info) length=(uint) (info->rc_pos - info->buffer); if (info->seek_not_done) { /* File touched, do seek */ - VOID(my_seek(info->file,info->pos_in_file,MY_SEEK_SET,MYF(0))); + if (my_seek(info->file,info->pos_in_file,MY_SEEK_SET,MYF(0)) == + MY_FILEPOS_ERROR) + DBUG_RETURN((info->error= -1)); info->seek_not_done=0; } info->rc_pos=info->buffer; diff --git a/mysys/my_vsnprintf.c b/mysys/my_vsnprintf.c index 63730926156..b394adf2a96 100644 --- a/mysys/my_vsnprintf.c +++ b/mysys/my_vsnprintf.c @@ -21,74 +21,49 @@ #include <stdarg.h> #include <m_ctype.h> - - -int my_vsnprintf(char* str, size_t n, const char* fmt, va_list ap) +int my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap) { - uint olen = 0, plen; - const char *tpos; - reg1 char *endpos; - reg2 char * par; - char* ebuff = str; - - endpos=ebuff; - tpos = fmt; + char *start=to, *end=to+n-1; - while (*tpos) + for (; *fmt ; fmt++) { - if (tpos[0] != '%') + if (fmt[0] != '%') { - if(olen + 1 >= n) + if (to == end) /* End of buffer */ break; - - *endpos++= *tpos++; /* Copy ordinary char */ - olen++; + *to++= *fmt; /* Copy ordinary char */ continue; } - if (*++tpos == '%') /* test if %% */ - { - olen--; - } - else + /* Skipp if max size is used (to be compatible with printf) */ + while (isdigit(*fmt) || *fmt == '.' || *fmt == '-') + fmt++; + if (*fmt == 's') /* String parameter */ { - /* Skipp if max size is used (to be compatible with printf) */ - while (isdigit(*tpos) || *tpos == '.' || *tpos == '-') - tpos++; - if (*tpos == 's') /* String parameter */ - { - par = va_arg(ap, char *); - plen = (uint) strlen(par); - if (olen + plen < n) /* Replace if possible */ - { - endpos=strmov(endpos,par); - tpos++; - olen+=plen; - continue; - } - } - else if (*tpos == 'd' || *tpos == 'u') /* Integer parameter */ + reg2 char *par = va_arg(ap, char *); + uint plen = (uint) strlen(par); + if ((uint) (end-to) > plen) /* Replace if possible */ { - register int iarg; - iarg = va_arg(ap, int); - if(olen + 16 >= n) break; - - if (*tpos == 'd') - plen= (uint) (int2str((long) iarg,endpos, -10) - endpos); - else - plen= (uint) (int2str((long) (uint) iarg,endpos,10)- endpos); - if (olen + plen < n) /* Replace parameter if possible */ - { - endpos+=plen; - tpos++; - olen+=plen; - continue; - } + to=strmov(to,par); + continue; } } - *endpos++='%'; /* % used as % or unknown code */ + else if (*fmt == 'd' || *fmt == 'u') /* Integer parameter */ + { + register int iarg; + if ((uint) (end-to) < 16) + break; + iarg = va_arg(ap, int); + if (*fmt == 'd') + to=int10_to_str((long) iarg,to, -10); + else + to=int10_to_str((long) (uint) iarg,to,10); + continue; + } + /* We come here on '%%', unknown code or too long parameter */ + if (to == end) + break; + *to++='%'; /* % used as % or unknown code */ } - *endpos='\0'; - /* End of errmessage */ - return olen; + *to='\0'; /* End of errmessage */ + return (uint) (to - start); } - diff --git a/scripts/safe_mysqld.sh b/scripts/safe_mysqld.sh index 43023e0fb8b..615670326bb 100644 --- a/scripts/safe_mysqld.sh +++ b/scripts/safe_mysqld.sh @@ -28,10 +28,13 @@ parse_arguments() { --socket=*) MYSQL_UNIX_PORT=`echo "$arg" | sed -e "s;--socket=;;"` ;; --port=*) MYSQL_TCP_PORT=`echo "$arg" | sed -e "s;--port=;;"` ;; --log=*) log=`echo "$arg" | sed -e "s;--log=;;"` ;; - --err-log=*) err_log=`echo "$arg" | sed -e "s;--err-log=;;"` ;; --basedir=*) MY_BASEDIR_VERSION=`echo "$arg" | sed -e "s;--basedir=;;"` ;; - --ledir=*) ledir=`echo "$arg" | sed -e "s;--ledir=;;"` ;; --user=*) user=`echo "$arg" | sed -e "s;--user=;;"` ;; + --ledir=*) ledir=`echo "$arg" | sed -e "s;--ledir=;;"` ;; + --err-log=*) err_log=`echo "$arg" | sed -e "s;--err-log=;;"` ;; + --open-files=*) open_files=`echo "$arg" | sed -e "s;--open-files=;;"` ;; + --core-file-size*) core_file_size=`echo "$arg" | sed -e "s;--core_file_size=;;"` ;; + --timezone=*) TZ=`echo "$arg" | sed -e "s;--timezone=;;"` ; export TZ; ;; esac done } @@ -105,6 +108,14 @@ if test -w / then # If we are root, change the err log to the right user. touch $err_log; chown $user $err_log + if test -n "$open_files" + then + ulimit -n $open_files + fi + if test -n "$core_file_size" + then + ulimit -c $core_file_size + fi fi # diff --git a/sql-bench/bench-init.pl.sh b/sql-bench/bench-init.pl.sh index 3f650885c21..ae847c1a28f 100755 --- a/sql-bench/bench-init.pl.sh +++ b/sql-bench/bench-init.pl.sh @@ -339,6 +339,15 @@ sub end_benchmark exit 0; } +sub print_time +{ + my ($estimated)=@_; + if ($estimated) + { print "Estimated time"; } + else + { print "Time"; } +} + # # Create a filename part for the machine that can be used for log file. # diff --git a/sql-bench/crash-me.sh b/sql-bench/crash-me.sh index 6bb3eab63f9..5c993e842bc 100755 --- a/sql-bench/crash-me.sh +++ b/sql-bench/crash-me.sh @@ -39,7 +39,7 @@ # "3-byte int" or "same as xxx". -$version="1.50"; +$version="1.51"; use DBI; use Getopt::Long; @@ -289,6 +289,11 @@ report("rename table","rename_table", $dbh->do("drop table crash_q1"); $dbh->do("drop table crash_q"); +report("truncate table","truncate_table", + "create table crash_q (a integer, b integer,c CHAR(10))", + "truncate table crash_q", + "drop table crash_q1"); + if ($dbh->do("create table crash_q (a integer, b integer,c CHAR(10))") && $dbh->do("create table crash_q1 (a integer, b integer,c CHAR(10) not null)")) { diff --git a/sql-bench/test-insert.sh b/sql-bench/test-insert.sh index e6690b043f1..13bcfb2f6a9 100755 --- a/sql-bench/test-insert.sh +++ b/sql-bench/test-insert.sh @@ -270,7 +270,7 @@ for ($i=1 ; $i <= $small_loop_count ; $i++) { if (!$error++) { - print "Warning: Got $found_rows rows when selecting a hole table of " . ($total_rows) . " rows\nContact the database or DBD author!\n"; + print "Warning: Got $found_rows rows when selecting a whole table of " . ($total_rows) . " rows\nContact the database or DBD author!\n"; } } $count+=$found_rows; @@ -280,44 +280,125 @@ $end_time=new Benchmark; print "Time for select_big ($small_loop_count:$count): " . timestr(timediff($end_time, $loop_time),"all") . "\n"; +# +# Do a lot of different ORDER BY queries +# + $loop_time=new Benchmark; -$estimated=0; -$rows=0; -$count=0; -for ($i=1 ; $i <= $small_loop_count/2 ; $i++) +$estimated=$rows=0; +for ($i=1 ; $i <= $small_loop_count ; $i++) { $rows+=fetch_all_rows($dbh,"select id from bench1 order by id",1); + $end_time=new Benchmark; + last if ($estimated=predict_query_time($loop_time,$end_time,\$i,$i, + $small_loop_count)); +} +if ($estimated) +{ print "Estimated time"; } +else +{ print "Time"; } +print " for order_by_big_key ($small_loop_count:$rows): " . + timestr(timediff($end_time, $loop_time),"all") . "\n"; + +$loop_time=new Benchmark; +$estimated=$rows=0; +for ($i=1 ; $i <= $small_loop_count ; $i++) +{ $rows+=fetch_all_rows($dbh,"select id from bench1 order by id desc",1); - $count+=2; $end_time=new Benchmark; - last if ($estimated=predict_query_time($loop_time,$end_time,\$count,$count, + last if ($estimated=predict_query_time($loop_time,$end_time,\$i,$i, $small_loop_count)); } if ($estimated) { print "Estimated time"; } else { print "Time"; } -print " for order_by_key ($count:$rows): " . +print " for order_by_big_key_desc ($small_loop_count:$rows): " . timestr(timediff($end_time, $loop_time),"all") . "\n"; $loop_time=new Benchmark; -$estimated=0; -$rows=0; -$count=0; -for ($i=1 ; $i <= $small_loop_count/2 ; $i++) +$estimated=$rows=0; +for ($i=1 ; $i <= $small_loop_count ; $i++) { - $rows+=fetch_all_rows($dbh,"select id2 from bench1 order by id2",1); - $rows+=fetch_all_rows($dbh,"select id2 from bench1 order by id2 desc",1); - $count+=2; + $rows+=fetch_all_rows($dbh,"select id3 from bench1 order by id3",1); $end_time=new Benchmark; - last if ($estimated=predict_query_time($loop_time,$end_time,\$count,$count, + last if ($estimated=predict_query_time($loop_time,$end_time,\$i,$i, + $small_loop_count)); +} +if ($estimated) +{ print "Estimated time"; } +else +{ print "Time"; } +print " for order_by_big_key2 ($small_loop_count:$rows): " . + timestr(timediff($end_time, $loop_time),"all") . "\n"; + +$loop_time=new Benchmark; +$estimated=$rows=0; +for ($i=1 ; $i <= $small_loop_count ; $i++) +{ + $rows+=fetch_all_rows($dbh,"select id2 from bench1 order by id3",1); + $end_time=new Benchmark; + last if ($estimated=predict_query_time($loop_time,$end_time,\$i,$i, $small_loop_count)); } if ($estimated) { print "Estimated time"; } else { print "Time"; } -print " for order_by ($count:$rows): " . +print " for order_by_big_key_diff ($small_loop_count:$rows): " . + timestr(timediff($end_time, $loop_time),"all") . "\n"; + + +$loop_time=new Benchmark; +$estimated=$rows=0; +for ($i=1 ; $i <= $small_loop_count ; $i++) +{ + $rows+=fetch_all_rows($dbh,"select id from bench1 order by id2,id3",1); + $end_time=new Benchmark; + last if ($estimated=predict_query_time($loop_time,$end_time,\$i,$i, + $small_loop_count)); +} +if ($estimated) +{ print "Estimated time"; } +else +{ print "Time"; } +print " for order_by_big ($small_loop_count:$rows): " . + timestr(timediff($end_time, $loop_time),"all") . "\n"; + +$loop_time=new Benchmark; +$estimated=$rows=0; +for ($i=1 ; $i <= $small_loop_count ; $i++) +{ + $start=$opt_loop_count/$small_loop_count*$i; + $end=$start+$i; + $rows+=fetch_all_rows($dbh,"select dummy1 from bench1 where id>=$start and id <= $end order by id",1); + $end_time=new Benchmark; + last if ($estimated=predict_query_time($loop_time,$end_time,\$i,$i, + $small_loop_count)); +} +if ($estimated) +{ print "Estimated time"; } +else +{ print "Time"; } +print " for order_by_key ($small_loop_count:$rows): " . + timestr(timediff($end_time, $loop_time),"all") . "\n"; + +$loop_time=new Benchmark; +$estimated=$rows=0; +for ($i=1 ; $i <= $small_loop_count ; $i++) +{ + $start=$opt_loop_count/$small_loop_count*$i; + $end=$start+$small_loop_count; + $rows+=fetch_all_rows($dbh,"select id2 from bench1 where id3>=$start and id3 <= $end order by id3",1); + $end_time=new Benchmark; + last if ($estimated=predict_query_time($loop_time,$end_time,\$i,$i, + $small_loop_count)); +} +if ($estimated) +{ print "Estimated time"; } +else +{ print "Time"; } +print " for order_by_key2_diff ($small_loop_count:$rows): " . timestr(timediff($end_time, $loop_time),"all") . "\n"; # @@ -417,6 +498,7 @@ if ($limits->{'group_functions'}) $loop_time=new Benchmark; $count=1; + $estimated=0; for ($tests=0 ; $tests < $small_loop_count ; $tests++) { $sth=$dbh->prepare($query="select count(*) from bench1") or die $DBI::errstr; @@ -492,9 +574,12 @@ if ($limits->{'group_functions'}) print "Warning: '$query' returned wrong number of rows\n"; } } + $end_time=new Benchmark; + last if ($estimated=predict_query_time($loop_time,$end_time,\$count,$tests, + $small_loop_count)); } - $end_time=new Benchmark; - print "Time for select_group ($count): " . + print_time($estimated); + print " for select_group ($count): " . timestr(timediff($end_time, $loop_time),"all") . "\n"; $loop_time=new Benchmark; diff --git a/sql-bench/test-select.sh b/sql-bench/test-select.sh index 160a10a1c33..32059d6ac8a 100755 --- a/sql-bench/test-select.sh +++ b/sql-bench/test-select.sh @@ -205,10 +205,7 @@ for ($i=0 ; $i < $opt_small_loop_count ; $i++) $opt_small_loop_count)); } -if ($estimated) -{ print "Estimated time"; } -else -{ print "Time"; } +print_time($estimated); print " for select_range ($count:$rows): " . timestr(timediff($end_time, $loop_time),"all") . "\n"; @@ -243,10 +240,7 @@ if ($limits->{'group_functions'}) last if ($estimated=predict_query_time($loop_time,$end_time,\$count, $tests+1, $opt_loop_count)); } - if ($estimated) - { print "Estimated time"; } - else - { print "Time"; } + print_time($estimated); print " for min_max_on_key ($count): " . timestr(timediff($end_time, $loop_time),"all") . "\n"; @@ -267,10 +261,7 @@ if ($limits->{'group_functions'}) last if ($estimated=predict_query_time($loop_time,$end_time,\$count, $tests+1, $opt_loop_count)); } - if ($estimated) - { print "Estimated time"; } - else - { print "Time"; } + print_time($estimated); print " for count_on_key ($count): " . timestr(timediff($end_time, $loop_time),"all") . "\n\n"; @@ -278,7 +269,7 @@ if ($limits->{'group_functions'}) $rows=0; for ($i=0 ; $i < $opt_medium_loop_count ; $i++) { - fetch_all_rows($dbh,"select grp,count(*) from bench1 group by grp"); + $rows+=fetch_all_rows($dbh,"select grp,count(*) from bench1 group by grp"); } $end_time=new Benchmark; print "Time for count_group_on_key_parts ($i:$rows): " . @@ -289,54 +280,74 @@ if ($limits->{'group_functions'}) { print "Testing count(distinct) on the table\n"; $loop_time=new Benchmark; - $rows=0; + $rows=$estimated=$count=0; for ($i=0 ; $i < $opt_medium_loop_count ; $i++) { + $count+=2; $rows+=fetch_all_rows($dbh,"select count(distinct region) from bench1"); $rows+=fetch_all_rows($dbh,"select count(distinct grp) from bench1"); + $end_time=new Benchmark; + last if ($estimated=predict_query_time($loop_time,$end_time,\$count,$i+1, + $opt_medium_loop_count)); } - $end_time=new Benchmark; - print "Time for count_distinct ($i:$rows): " . + print_time($estimated); + print " for count_distinct ($count:$rows): " . timestr(timediff($end_time, $loop_time),"all") . "\n"; $loop_time=new Benchmark; - $rows=0; + $rows=$estimated=$count=0; for ($i=0 ; $i < $opt_medium_loop_count ; $i++) { + $count++; $rows+=fetch_all_rows($dbh,"select region,count(distinct idn) from bench1 group by region"); + $end_time=new Benchmark; + last if ($estimated=predict_query_time($loop_time,$end_time,\$count,$i+1, + $opt_medium_loop_count)); } - $end_time=new Benchmark; - print "Time for count_distinct_group_on_key ($i:$rows): " . + print_time($estimated); + print " for count_distinct_group_on_key ($count:$rows): " . timestr(timediff($end_time, $loop_time),"all") . "\n"; $loop_time=new Benchmark; - $rows=0; + $rows=$estimated=$count=0; for ($i=0 ; $i < $opt_medium_loop_count ; $i++) { + $count++; $rows+=fetch_all_rows($dbh,"select grp,count(distinct idn) from bench1 group by grp"); + $end_time=new Benchmark; + last if ($estimated=predict_query_time($loop_time,$end_time,\$count,$i+1, + $opt_medium_loop_count)); } - $end_time=new Benchmark; - print "Time for count_distinct_group_on_key_parts ($i:$rows): " . + print_time($estimated); + print " for count_distinct_group_on_key_parts ($count:$rows): " . timestr(timediff($end_time, $loop_time),"all") . "\n"; $loop_time=new Benchmark; - $rows=0; + $rows=$estimated=$count=0; for ($i=0 ; $i < $opt_medium_loop_count ; $i++) { + $count++; $rows+=fetch_all_rows($dbh,"select grp,count(distinct rev_idn) from bench1 group by grp"); + $end_time=new Benchmark; + last if ($estimated=predict_query_time($loop_time,$end_time,\$count,$i+1, + $opt_medium_loop_count)); } - $end_time=new Benchmark; - print "Time for count_distinct_group ($i:$rows): " . + print_time($estimated); + print " for count_distinct_group ($count:$rows): " . timestr(timediff($end_time, $loop_time),"all") . "\n"; $loop_time=new Benchmark; - $rows=0; + $rows=$estimated=$count=0; for ($i=0 ; $i < $opt_medium_loop_count ; $i++) { + $count++; $rows+=fetch_all_rows($dbh,"select idn,count(distinct region) from bench1 group by idn"); + $end_time=new Benchmark; + last if ($estimated=predict_query_time($loop_time,$end_time,\$count,$i+1, + $opt_medium_loop_count)); } - $end_time=new Benchmark; - print "Time for count_distinct_big ($i:$rows): " . + print_time($estimated); + print " for count_distinct_big ($count:$rows): " . timestr(timediff($end_time, $loop_time),"all") . "\n"; } diff --git a/sql/filesort.cc b/sql/filesort.cc index 6d6bbe00182..220ff69a3e8 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -38,8 +38,8 @@ if (my_b_write((file),(byte*) (from),param->ref_length)) \ typedef struct st_buffpek { /* Struktur om sorteringsbuffrarna */ my_off_t file_pos; /* Where we are in the sort file */ - ha_rows count; /* Number of rows in table */ uchar *base,*key; /* key pointers */ + ha_rows count; /* Number of rows in table */ ulong mem_count; /* numbers of keys in memory */ ulong max_keys; /* Max keys in buffert */ } BUFFPEK; @@ -98,7 +98,6 @@ ha_rows filesort(TABLE **table, SORT_FIELD *sortorder, uint s_length, BUFFPEK *buffpek; ha_rows records; uchar **sort_keys; - gptr save_1,save_2; IO_CACHE tempfile,*selected_records_file,*outfile; SORTPARAM param; DBUG_ENTER("filesort"); @@ -109,7 +108,6 @@ ha_rows filesort(TABLE **table, SORT_FIELD *sortorder, uint s_length, outfile= table[0]->io_cache; my_b_clear(&tempfile); - save_1=save_2=0; buffpek= (BUFFPEK *) NULL; sort_keys= (uchar **) NULL; error= 1; maxbuffer=1; param.ref_length= table[0]->file->ref_length; @@ -148,7 +146,7 @@ ha_rows filesort(TABLE **table, SORT_FIELD *sortorder, uint s_length, else { table[0]->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);/* Get record-count */ - records=table[0]->file->records+EXTRA_RECORDS; + records=table[0]->file->estimate_number_of_rows(); selected_records_file= 0; } if (param.sort_length == param.ref_length && records > param.max_rows) @@ -160,16 +158,11 @@ ha_rows filesort(TABLE **table, SORT_FIELD *sortorder, uint s_length, goto err; #endif - /* Reserve memory for IO_CACHE files */ - if (! (save_1=my_malloc(DISK_BUFFER_SIZE,MYF(MY_WME))) || - ! (save_2=my_malloc(DISK_BUFFER_SIZE,MYF(MY_WME)))) - goto err; - memavl=sortbuff_size; while (memavl >= MIN_SORT_MEMORY) { - if ((records+1)*(param.sort_length+sizeof(char*))+sizeof(BUFFPEK)*10 < - (ulong) memavl) + if ((ulonglong) (records+1)*(param.sort_length+sizeof(char*))+sizeof(BUFFPEK)*10 < + (ulonglong) memavl) param.keys=(uint) records+1; else { @@ -207,10 +200,6 @@ ha_rows filesort(TABLE **table, SORT_FIELD *sortorder, uint s_length, my_error(ER_OUTOFMEMORY,MYF(ME_ERROR+ME_WAITTANG),sortbuff_size); goto err; } - my_free(save_1,MYF(0)); /* Free for later use */ - my_free(save_2,MYF(0)); - save_1=save_2=0; - param.sort_form= table[0]; param.end=(param.local_sortorder=sortorder)+s_length; if ((records=find_all_keys(¶m,select,sort_keys,buffpek,&maxbuffer, @@ -252,8 +241,6 @@ ha_rows filesort(TABLE **table, SORT_FIELD *sortorder, uint s_length, #endif x_free((gptr) sort_keys); x_free((gptr) buffpek); - x_free(save_1); - x_free(save_2); close_cached_file(&tempfile); if (my_b_inited(outfile)) { @@ -382,6 +369,7 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select, } if (*killed) { + DBUG_PRINT("info",("Sort killed by user")); (void) file->extra(HA_EXTRA_NO_CACHE); file->rnd_end(); DBUG_RETURN(HA_POS_ERROR); /* purecov: inspected */ diff --git a/sql/ha_berkeley.cc b/sql/ha_berkeley.cc index 6cf97f16bb8..490a6db89e5 100644 --- a/sql/ha_berkeley.cc +++ b/sql/ha_berkeley.cc @@ -25,8 +25,9 @@ We will need an updated Berkeley DB version for this. - Killing threads that has got a 'deadlock' - SHOW TABLE STATUS should give more information about the table. - - Get a more accurate count of the number of rows. - We could store the found number of rows when the table is scanned. + - Get a more accurate count of the number of rows (estimate_number_of_rows()). + We could store the found number of rows when the table is scanned and + then increment the counter for each attempted write. - We will need a manager thread that calls flush_logs, removes old logs and makes checkpoints at given intervals. - When not using UPDATE IGNORE, don't make a sub transaction but abort @@ -42,7 +43,6 @@ - LOCK TABLES - CHAR keys - BLOBS - - delete from t1; */ @@ -60,6 +60,7 @@ #define HA_BERKELEY_ROWS_IN_TABLE 10000 /* to get optimization right */ #define HA_BERKELEY_RANGE_COUNT 100 +#define HA_BERKELEY_MAX_ROWS 10000000 /* Max rows in table */ const char *ha_berkeley_ext=".db"; bool berkeley_skip=0; @@ -1297,7 +1298,7 @@ void ha_berkeley::info(uint flag) DBUG_ENTER("info"); if (flag & HA_STATUS_VARIABLE) { - records = HA_BERKELEY_ROWS_IN_TABLE; // Just to get optimisations right + records = estimate_number_of_rows(); // Just to get optimisations right deleted = 0; } else if (flag & HA_STATUS_ERRKEY) @@ -1607,4 +1608,21 @@ void ha_berkeley::update_auto_primary_key() pthread_mutex_unlock(&share->mutex); } +/* + Return an estimated of the number of rows in the table. + Used when sorting to allocate buffers and by the optimizer. +*/ + +ha_rows ha_berkeley::estimate_number_of_rows() +{ + ulonglong max_ident; + ulonglong max_rows=table->max_rows ? table->max_rows : HA_BERKELEY_MAX_ROWS; + if (!hidden_primary_key) + return (ha_rows) max_rows; + pthread_mutex_lock(&share->mutex); + max_ident=share->auto_ident+EXTRA_RECORDS; + pthread_mutex_unlock(&share->mutex); + return (ha_rows) min(max_ident,max_rows); +} + #endif /* HAVE_BERKELEY_DB */ diff --git a/sql/ha_berkeley.h b/sql/ha_berkeley.h index 84061ae09be..1d1de613ce0 100644 --- a/sql/ha_berkeley.h +++ b/sql/ha_berkeley.h @@ -91,7 +91,8 @@ class ha_berkeley: public handler uint max_keys() const { return MAX_KEY-1; } uint max_key_parts() const { return MAX_REF_PARTS; } uint max_key_length() const { return MAX_KEY_LENGTH; } - uint extra_rec_buf_length() { return BDB_HIDDEN_PRIMARY_KEY_LENGTH; } + uint extra_rec_buf_length() { return BDB_HIDDEN_PRIMARY_KEY_LENGTH; } + ha_rows estimate_number_of_rows(); bool fast_key_read() { return 1;} bool has_transactions() { return 1;} diff --git a/sql/handler.h b/sql/handler.h index 84c14538f4b..bdc58ee7356 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -203,6 +203,7 @@ public: virtual bool fast_key_read() { return 0;} virtual bool has_transactions(){ return 0;} virtual uint extra_rec_buf_length() { return 0; } + virtual ha_rows estimate_number_of_rows() { return records+EXTRA_RECORDS; } virtual int index_init(uint idx) { active_index=idx; return 0;} virtual int index_end() {return 0; } diff --git a/sql/item_create.cc b/sql/item_create.cc index 8c62643b35a..8e6332d4e16 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -352,11 +352,6 @@ Item *create_func_to_days(Item* a) return new Item_func_to_days(a); } -Item *create_func_truncate (Item *a, Item *b) -{ - return new Item_func_round(a,b,1); -} - Item *create_func_ucase(Item* a) { return new Item_func_ucase(a); diff --git a/sql/item_create.h b/sql/item_create.h index aa617946d98..de2726b32b0 100644 --- a/sql/item_create.h +++ b/sql/item_create.h @@ -81,7 +81,6 @@ Item *create_func_tan(Item* a);; Item *create_func_time_format(Item *a, Item *b); Item *create_func_time_to_sec(Item* a); Item *create_func_to_days(Item* a); -Item *create_func_truncate (Item *a, Item *b); Item *create_func_ucase(Item* a); Item *create_func_version(void); Item *create_func_weekday(Item* a); diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 6b8b3762aa1..39bbdcaff1f 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1598,7 +1598,7 @@ String *Item_load_file::val_str(String *str) if (!(file_name= args[0]->val_str(str)) || !(current_thd->master_access & FILE_ACL) || - !my_stat(file_name->c_ptr(), &stat_info, MYF(MY_FAE))) + !my_stat(file_name->c_ptr(), &stat_info, MYF(MY_WME))) goto err; if (!(stat_info.st_mode & S_IROTH)) { diff --git a/sql/lex.h b/sql/lex.h index a75fa07c3b7..503ce6998bb 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -302,6 +302,7 @@ static SYMBOL symbols[] = { { "TINYTEXT", SYM(TINYTEXT),0,0}, { "TINYINT", SYM(TINYINT),0,0}, { "TRAILING", SYM(TRAILING),0,0}, + { "TRUNCATE", SYM(TRUNCATE_SYM),0,0}, { "TO", SYM(TO_SYM),0,0}, { "TYPE", SYM(TYPE_SYM),0,0}, { "UNION", SYM(UNION_SYM),0,0}, @@ -443,7 +444,6 @@ static SYMBOL sql_functions[] = { { "TIME_TO_SEC", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_time_to_sec)}, { "TO_DAYS", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_to_days)}, { "TRIM", SYM(TRIM),0,0}, - { "TRUNCATE", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_truncate )}, { "UCASE", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ucase)}, { "UPPER", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ucase)}, { "UNIQUE_USERS", SYM(UNIQUE_USERS),0,0}, diff --git a/sql/lock.cc b/sql/lock.cc index 4c7ae8e950b..c85983b65d6 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -70,8 +70,8 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd,TABLE **tables,uint count) thd->proc_info="Waiting for table"; pthread_mutex_unlock(&thd->mysys_var->mutex); - while (global_read_lock && ! thd->killed || - thd->version != refresh_version) + while (global_read_lock && ! thd->killed && + thd->version == refresh_version) { (void) pthread_cond_wait(&COND_refresh,&LOCK_open); } diff --git a/sql/log.cc b/sql/log.cc index bf99bb32f09..7172d043552 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -25,8 +25,6 @@ #include <stdarg.h> #include <m_ctype.h> // For test_if_number - - MYSQL_LOG mysql_log,mysql_update_log,mysql_slow_log,mysql_bin_log; extern I_List<i_string> binlog_do_db, binlog_ignore_db; @@ -75,26 +73,25 @@ static int find_uniq_filename(char *name) DBUG_RETURN(0); } - - -MYSQL_LOG::MYSQL_LOG(): file(0),index_file(0),last_time(0),query_start(0), - name(0), log_type(LOG_CLOSED),write_error(0),inited(0), - no_rotate(0) +MYSQL_LOG::MYSQL_LOG(): last_time(0), query_start(0), + name(0), log_type(LOG_CLOSED),write_error(0), + inited(0), opened(0), no_rotate(0) { /* We don't want to intialize LOCK_Log here as the thread system may not have been initailized yet. We do it instead at 'open'. */ - index_file_name[0] = 0; + index_file_name[0] = 0; + bzero((char*) &log_file,sizeof(log_file)); } MYSQL_LOG::~MYSQL_LOG() { if (inited) - { - (void) pthread_mutex_destroy(&LOCK_log); - (void) pthread_mutex_destroy(&LOCK_index); - } + { + (void) pthread_mutex_destroy(&LOCK_log); + (void) pthread_mutex_destroy(&LOCK_index); + } } void MYSQL_LOG::set_index_file_name(const char* index_file_name) @@ -106,6 +103,7 @@ void MYSQL_LOG::set_index_file_name(const char* index_file_name) this->index_file_name[0] = 0; } + int MYSQL_LOG::generate_new_name(char *new_name, const char *log_name) { if (log_type == LOG_NORMAL) @@ -129,58 +127,60 @@ int MYSQL_LOG::generate_new_name(char *new_name, const char *log_name) void MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg, const char *new_name) { + MY_STAT tmp_stat; + char buff[512]; + File file= -1; + bool do_magic; if (!inited) { inited=1; (void) pthread_mutex_init(&LOCK_log,NULL); (void) pthread_mutex_init(&LOCK_index, NULL); - if(log_type_arg == LOG_BIN && *fn_ext(log_name)) + if (log_type_arg == LOG_BIN && *fn_ext(log_name)) no_rotate = 1; } - + log_type=log_type_arg; - name=my_strdup(log_name,MYF(0)); + if (!(name=my_strdup(log_name,MYF(MY_WME)))) + goto err; if (new_name) strmov(log_file_name,new_name); else if (generate_new_name(log_file_name, name)) - return; + goto err; if (log_type == LOG_BIN && !index_file_name[0]) fn_format(index_file_name, name, mysql_data_home, ".index", 6); db[0]=0; - MY_STAT tmp_stat; - bool do_magic = ((log_type == LOG_BIN) && !my_stat(log_file_name, - &tmp_stat, MYF(0))); + do_magic = ((log_type == LOG_BIN) && !my_stat(log_file_name, + &tmp_stat, MYF(0))); - file=my_fopen(log_file_name,O_APPEND | O_WRONLY | O_BINARY, - MYF(MY_WME | ME_WAITTANG)); - if (!file) - { - my_free(name,MYF(0)); - name=0; - log_type=LOG_CLOSED; - return; - } + if ((file=my_open(log_file_name,O_APPEND | O_WRONLY | O_BINARY, + MYF(MY_WME | ME_WAITTANG))) < 0 || + init_io_cache(&log_file, file, IO_SIZE, WRITE_CACHE, + my_tell(file,MYF(MY_WME)), 0, MYF(MY_WME | MY_NABP))) + goto err; if (log_type == LOG_NORMAL) { + char *end; #ifdef __NT__ - fprintf(file, "%s, Version: %s, started with:\nTCP Port: %d, Named Pipe: %s\n", my_progname, server_version, mysql_port, mysql_unix_port); + sprintf(buff, "%s, Version: %s, started with:\nTCP Port: %d, Named Pipe: %s\n", my_progname, server_version, mysql_port, mysql_unix_port); #else - fprintf(file, "%s, Version: %s, started with:\nTcp port: %d Unix socket: %s\n", my_progname,server_version,mysql_port,mysql_unix_port); + sprintf(buff, "%s, Version: %s, started with:\nTcp port: %d Unix socket: %s\n", my_progname,server_version,mysql_port,mysql_unix_port); #endif - fprintf(file,"Time Id Command Argument\n"); - (void) fflush(file); + end=strmov(strend(buff),"Time Id Command Argument\n"); + if (my_b_write(&log_file,buff,(uint) (end-buff)) || + flush_io_cache(&log_file)) + goto err; } else if (log_type == LOG_NEW) { time_t skr=time(NULL); struct tm tm_tmp; localtime_r(&skr,&tm_tmp); - - fprintf(file,"# %s, Version: %s at %02d%02d%02d %2d:%02d:%02d\n", + sprintf(buff,"# %s, Version: %s at %02d%02d%02d %2d:%02d:%02d\n", my_progname,server_version, tm_tmp.tm_year % 100, tm_tmp.tm_mon+1, @@ -188,45 +188,49 @@ void MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg, tm_tmp.tm_hour, tm_tmp.tm_min, tm_tmp.tm_sec); - (void) fflush(file); + if (my_b_write(&log_file,buff,(uint) strlen(buff)) || + flush_io_cache(&log_file)) + goto err; } else if (log_type == LOG_BIN) { - // Explanation of the boolean black magic: // // if we are supposed to write magic number try write // clean up if failed // then if index_file has not been previously opened, try to open it // clean up if failed - if((do_magic && my_fwrite(file, (byte*)BINLOG_MAGIC, 4, - MYF(MY_NABP|MY_WME)) || - (!index_file && - !(index_file = my_fopen(index_file_name,O_APPEND | O_BINARY | O_RDWR, - MYF(MY_WME)))))) - { - my_fclose(file,MYF(MY_WME)); - my_free(name,MYF(0)); - name=0; - file=0; - log_type=LOG_CLOSED; - return; - } + + if ((do_magic && my_b_write(&log_file, (byte*) BINLOG_MAGIC, 4)) || + (index_file < 0 && + (index_file = my_open(index_file_name,O_APPEND | O_BINARY | O_RDWR, + MYF(MY_WME))) < 0)) + goto err; Start_log_event s; - s.write(file); + s.write(&log_file); pthread_mutex_lock(&LOCK_index); - my_fseek(index_file, 0L, MY_SEEK_END, MYF(MY_WME)); - fprintf(index_file, "%s\n", log_file_name); - fflush(index_file); + my_write(index_file, log_file_name,strlen(log_file_name), MYF(0)); + my_write(index_file, "\n",1, MYF(0)); pthread_mutex_unlock(&LOCK_index); } + return; + +err: + if (file >= 0) + my_close(file,MYF(0)); + end_io_cache(&log_file); + x_free(name); name=0; + log_type=LOG_CLOSED; + + return; + } int MYSQL_LOG::get_current_log(LOG_INFO* linfo) { pthread_mutex_lock(&LOCK_log); - strmake(linfo->log_file_name, log_file_name, sizeof(linfo->log_file_name)); - linfo->pos = my_ftell(file, MYF(MY_WME)); + strmake(linfo->log_file_name, log_file_name, sizeof(linfo->log_file_name)-1); + linfo->pos = my_b_tell(&log_file); pthread_mutex_unlock(&LOCK_log); return 0; } @@ -234,50 +238,85 @@ int MYSQL_LOG::get_current_log(LOG_INFO* linfo) // if log_name is "" we stop at the first entry int MYSQL_LOG::find_first_log(LOG_INFO* linfo, const char* log_name) { - // mutex needed because we need to make sure the file pointer does not move - // from under our feet - if(!index_file) return LOG_INFO_INVALID; + if (index_file < 0) + return LOG_INFO_INVALID; int error = 0; char* fname = linfo->log_file_name; int log_name_len = (uint) strlen(log_name); + IO_CACHE io_cache; + // mutex needed because we need to make sure the file pointer does not move + // from under our feet pthread_mutex_lock(&LOCK_index); - if(my_fseek(index_file, 0L, MY_SEEK_SET, MYF(MY_WME) ) == MY_FILEPOS_ERROR) + if (init_io_cache(&io_cache, index_file, IO_SIZE, READ_CACHE, (my_off_t) 0, + 0, MYF(MY_WME))) + { + error = LOG_INFO_SEEK; + goto err; + } + for(;;) + { + uint length; + if (!(length=my_b_gets(&io_cache, fname, FN_REFLEN))) { - error = LOG_INFO_SEEK; + error = !io_cache.error ? LOG_INFO_EOF : LOG_INFO_IO; goto err; } - for(;;) + // if the log entry matches, empty string matching anything + if (!log_name_len || + (log_name_len == length+1 && fname[log_name_len] == '\n' && + !memcmp(fname, log_name, log_name_len))) { - if(!fgets(fname, FN_REFLEN, index_file)) - { - error = feof(index_file) ? LOG_INFO_EOF : LOG_INFO_IO; - goto err; - } - - // if the log entry matches, empty string matching anything - if(!log_name_len || (fname[log_name_len] == '\n' && - !memcmp(fname, log_name, log_name_len))) - { - if(log_name_len) - fname[log_name_len] = 0; // to kill \n - else - { - *(strend(fname) - 1) = 0; - } - linfo->index_file_offset = my_ftell(index_file, MYF(MY_WME)); - break; - } + fname[length-1]=0; // remove last \n + linfo->index_file_offset = my_b_tell(&io_cache); + break; } - + } error = 0; + err: pthread_mutex_unlock(&LOCK_index); + end_io_cache(&io_cache); return error; } + +int MYSQL_LOG::find_next_log(LOG_INFO* linfo) +{ + // mutex needed because we need to make sure the file pointer does not move + // from under our feet + if (!index_file) return LOG_INFO_INVALID; + int error = 0; + char* fname = linfo->log_file_name; + IO_CACHE io_cache; + uint length; + + pthread_mutex_lock(&LOCK_index); + if (init_io_cache(&io_cache, index_file, IO_SIZE, + READ_CACHE, (my_off_t) linfo->index_file_offset, 0, + MYF(MY_WME))) + { + error = LOG_INFO_SEEK; + goto err; + } + if (!(length=my_b_gets(&io_cache, fname, FN_REFLEN))) + { + error = !io_cache.error ? LOG_INFO_EOF : LOG_INFO_IO; + goto err; + } + fname[length-1]=0; // kill /n + linfo->index_file_offset = my_b_tell(&io_cache); + error = 0; + +err: + pthread_mutex_unlock(&LOCK_index); + end_io_cache(&io_cache); + return error; +} + + int MYSQL_LOG::purge_logs(THD* thd, const char* to_log) { if(!index_file) return LOG_INFO_INVALID; @@ -409,63 +448,21 @@ err: } -int MYSQL_LOG::find_next_log(LOG_INFO* linfo) -{ - // mutex needed because we need to make sure the file pointer does not move - // from under our feet - if(!index_file) return LOG_INFO_INVALID; - int error = 0; - char* fname = linfo->log_file_name; - char* end ; - - pthread_mutex_lock(&LOCK_index); - if(linfo->fatal) - { - error = LOG_INFO_FATAL; - goto err; - } - - if(my_fseek(index_file, linfo->index_file_offset, MY_SEEK_SET, MYF(MY_WME) ) == MY_FILEPOS_ERROR) - { - error = LOG_INFO_SEEK; - goto err; - } - - if(!fgets(fname, FN_REFLEN, index_file)) - { - error = feof(index_file) ? LOG_INFO_EOF : LOG_INFO_IO; - goto err; - } - - end = strend(fname) - 1; - *end = 0; // kill /n - linfo->index_file_offset = ftell(index_file); - error = 0; -err: - pthread_mutex_unlock(&LOCK_index); - return error; -} - - // we assume that buf has at least FN_REFLEN bytes alloced void MYSQL_LOG::make_log_name(char* buf, const char* log_ident) { - if(inited) - { - int dir_len = dirname_length(log_file_name); - int ident_len = (uint) strlen(log_ident); - if(dir_len + ident_len + 1 > FN_REFLEN) - { - buf[0] = 0; - return; // protection agains malicious buffer overflow - } + buf[0] = 0; // In case of error + if (inited) + { + int dir_len = dirname_length(log_file_name); + int ident_len = (uint) strlen(log_ident); + if (dir_len + ident_len + 1 > FN_REFLEN) + return; // protection agains malicious buffer overflow - memcpy(buf, log_file_name, dir_len); - memcpy(buf + dir_len, log_ident, ident_len + 1); // this takes care of \0 - // at the end - } - else - buf[0] = 0; + memcpy(buf, log_file_name, dir_len); + // copy filename + end null + memcpy(buf + dir_len, log_ident, ident_len + 1); + } } bool MYSQL_LOG::is_active(const char* log_file_name) @@ -475,15 +472,17 @@ bool MYSQL_LOG::is_active(const char* log_file_name) void MYSQL_LOG::new_file() { - if (file) + // only rotate open logs that are marked non-rotatable + // (binlog with constant name are non-rotatable) + if (is_open() && ! no_rotate) { - if(no_rotate) // do not rotate logs that are marked non-rotatable - return; // ( for binlog with constant name) - char new_name[FN_REFLEN], *old_name=name; VOID(pthread_mutex_lock(&LOCK_log)); if (generate_new_name(new_name, name)) + { + VOID(pthread_mutex_unlock(&LOCK_log)); return; // Something went wrong + } if (log_type == LOG_BIN) { /* @@ -491,15 +490,13 @@ void MYSQL_LOG::new_file() to change base names at some point. */ Rotate_log_event r(new_name+dirname_length(new_name)); - r.write(file); + r.write(&log_file); VOID(pthread_cond_broadcast(&COND_binlog_update)); } name=0; close(); open(old_name, log_type, new_name); my_free(old_name,MYF(0)); - if (!file) // Something went wrong - log_type=LOG_CLOSED; last_time=query_start=0; write_error=0; VOID(pthread_mutex_unlock(&LOCK_log)); @@ -514,7 +511,10 @@ void MYSQL_LOG::write(THD *thd,enum enum_server_command command, { va_list args; va_start(args,format); + char buff[32]; VOID(pthread_mutex_lock(&LOCK_log)); + + /* Test if someone closed after the is_open test */ if (log_type != LOG_CLOSED) { time_t skr; @@ -544,28 +544,30 @@ void MYSQL_LOG::write(THD *thd,enum enum_server_command command, struct tm *start; localtime_r(&skr,&tm_tmp); start=&tm_tmp; - if (fprintf(file,"%02d%02d%02d %2d:%02d:%02d\t", - start->tm_year % 100, - start->tm_mon+1, - start->tm_mday, - start->tm_hour, - start->tm_min, - start->tm_sec) < 0) + /* Note that my_b_write() assumes it knows the length for this */ + sprintf(buff,"%02d%02d%02d %2d:%02d:%02d\t", + start->tm_year % 100, + start->tm_mon+1, + start->tm_mday, + start->tm_hour, + start->tm_min, + start->tm_sec); + if (my_b_write(&log_file,buff,16)) error=errno; } - else if (fputs("\t\t",file) < 0) + else if (my_b_write(&log_file,"\t\t",2) < 0) error=errno; - if (fprintf(file,"%7ld %-10.10s", - id,command_name[(uint) command]) < 0) + sprintf(buff,"%7ld %-10.10s", id,command_name[(uint) command]); + if (my_b_write(&log_file,buff,strlen(buff))) error=errno; if (format) { - if (fputc(' ',file) < 0 || vfprintf(file,format,args) < 0) + if (my_b_write(&log_file," ",1) || + my_b_printf(&log_file,format,args) == (uint) -1) error=errno; } - if (fputc('\n',file) < 0) - error=errno; - if (fflush(file) < 0) + if (my_b_write(&log_file,"\n",1) || + flush_io_cache(&log_file)) error=errno; if (error && ! write_error) { @@ -585,7 +587,7 @@ void MYSQL_LOG::write(Query_log_event* event_info) if (is_open()) { VOID(pthread_mutex_lock(&LOCK_log)); - if (file) + if (is_open()) { THD *thd=event_info->thd; if ((!(thd->options & OPTION_BIN_LOG) && @@ -599,43 +601,38 @@ void MYSQL_LOG::write(Query_log_event* event_info) if (thd->last_insert_id_used) { Intvar_log_event e((uchar)LAST_INSERT_ID_EVENT, thd->last_insert_id); - if (e.write(file)) + if (e.write(&log_file)) { sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno); goto err; } } - if (thd->insert_id_used) { Intvar_log_event e((uchar)INSERT_ID_EVENT, thd->last_insert_id); - if(e.write(file)) + if (e.write(&log_file)) { sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno); goto err; } } - - if(thd->convert_set) + if (thd->convert_set) + { + char buf[1024] = "SET CHARACTER SET "; + char* p = strend(buf); + p = strmov(p, thd->convert_set->name); + int save_query_length = thd->query_length; + // just in case somebody wants it later + thd->query_length = (uint)(p - buf); + Query_log_event e(thd, buf); + if (e.write(&log_file)) { - char buf[1024] = "SET CHARACTER SET "; - char* p = strend(buf); - p = strmov(p, thd->convert_set->name); - int save_query_length = thd->query_length; - // just in case somebody wants it later - thd->query_length = (uint)(p - buf); - Query_log_event e(thd, buf); - if(e.write(file)) - { - sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno); - goto err; - } - - thd->query_length = save_query_length; // clean up - + sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno); + goto err; } - - if (event_info->write(file)) + thd->query_length = save_query_length; // clean up + } + if (event_info->write(&log_file) || flush_io_cache(&log_file)) { sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno); } @@ -651,13 +648,13 @@ void MYSQL_LOG::write(Load_log_event* event_info) if (is_open()) { VOID(pthread_mutex_lock(&LOCK_log)); - if (file) + if (is_open()) { THD *thd=event_info->thd; if ((thd->options & OPTION_BIN_LOG) || !(thd->master_access & PROCESS_ACL)) { - if (event_info->write(file)) + if (event_info->write(&log_file) || flush_io_cache(&log_file)) sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno); VOID(pthread_cond_broadcast(&COND_binlog_update)); } @@ -676,7 +673,7 @@ void MYSQL_LOG::write(THD *thd,const char *query, uint query_length, { time_t current_time; VOID(pthread_mutex_lock(&LOCK_log)); - if (file) + if (is_open()) { // Safety agains reopen int error=0; char buff[80],*end; @@ -695,37 +692,42 @@ void MYSQL_LOG::write(THD *thd,const char *query, uint query_length, last_time=current_time; struct tm tm_tmp; struct tm *start; + char buff[32]; localtime_r(¤t_time,&tm_tmp); start=&tm_tmp; - if (fprintf(file,"# Time: %02d%02d%02d %2d:%02d:%02d\n", - start->tm_year % 100, - start->tm_mon+1, - start->tm_mday, - start->tm_hour, - start->tm_min, - start->tm_sec) < 0) + /* Note that my_b_write() assumes it knows the length for this */ + sprintf(buff,"# Time: %02d%02d%02d %2d:%02d:%02d\n", + start->tm_year % 100, + start->tm_mon+1, + start->tm_mday, + start->tm_hour, + start->tm_min, + start->tm_sec); + if (my_b_write(&log_file,buff,24)) error=errno; } - if (fprintf(file, "# User@Host: %s [%s] @ %s [%s]\n", - thd->priv_user, - thd->user, - thd->host ? thd->host : "", - thd->ip ? thd->ip : "") < 0) - error=errno;; + if (my_b_printf(&log_file, "# User@Host: %s [%s] @ %s [%s]\n", + thd->priv_user, + thd->user, + thd->host ? thd->host : "", + thd->ip ? thd->ip : "")) + error=errno; } if (query_start) { /* For slow query log */ if (!(specialflag & SPECIAL_LONG_LOG_FORMAT)) current_time=time(NULL); - fprintf(file,"# Time: %lu Lock_time: %lu Rows_sent: %lu\n", - (ulong) (current_time - query_start), - (ulong) (thd->time_after_lock - query_start), - (ulong) thd->sent_row_count); + if (my_b_printf(&log_file, + "# Time: %lu Lock_time: %lu Rows_sent: %lu\n", + (ulong) (current_time - query_start), + (ulong) (thd->time_after_lock - query_start), + (ulong) thd->sent_row_count)) + error=errno; } if (thd->db && strcmp(thd->db,db)) { // Database changed - if (fprintf(file,"use %s;\n",thd->db) < 0) + if (my_b_printf(&log_file,"use %s;\n",thd->db)) error=errno; strmov(db,thd->db); } @@ -757,7 +759,8 @@ void MYSQL_LOG::write(THD *thd,const char *query, uint query_length, *end++=';'; *end++='\n'; *end=0; - if (fputs("SET ",file) < 0 || fputs(buff+1,file) < 0) + if (my_b_write(&log_file,"SET ",4) || + my_b_write(&log_file,buff+1,(uint) (end-buff)-1)) error=errno; } if (!query) @@ -765,10 +768,9 @@ void MYSQL_LOG::write(THD *thd,const char *query, uint query_length, query="#adminstrator command"; query_length=21; } - if (my_fwrite(file,(byte*) query,query_length,MYF(MY_NABP)) || - fputc(';',file) < 0 || fputc('\n',file) < 0) - error=errno; - if (fflush(file) < 0) + if (my_b_write(&log_file,(byte*) query,query_length) || + my_b_write(&log_file,";\n",2) || + flush_io_cache(&log_file)) error=errno; if (error && ! write_error) { @@ -780,51 +782,48 @@ void MYSQL_LOG::write(THD *thd,const char *query, uint query_length, } } - - +#ifdef TO_BE_REMOVED void MYSQL_LOG::flush() { - if (file) - if (fflush(file) < 0 && ! write_error) + if (is_open()) + if (flush_io_cache(log_file) && ! write_error) { write_error=1; sql_print_error(ER(ER_ERROR_ON_WRITE),name,errno); } } +#endif void MYSQL_LOG::close(bool exiting) { // One can't set log_type here! - if (file) + if (is_open()) { + File file=log_file.file; if (log_type == LOG_BIN) { Stop_log_event s; - s.write(file); + s.write(&log_file); VOID(pthread_cond_broadcast(&COND_binlog_update)); } - if (my_fclose(file,MYF(0)) < 0 && ! write_error) + end_io_cache(&log_file); + if (my_close(file,MYF(0)) < 0 && ! write_error) { write_error=1; sql_print_error(ER(ER_ERROR_ON_WRITE),name,errno); } - file=0; - } - if (name) - { - my_free(name,MYF(0)); - name=0; + log_type=LOG_CLOSED; } - - if (exiting && index_file) + if (exiting && index_file >= 0) { - if (my_fclose(index_file,MYF(0)) < 0 && ! write_error) + if (my_close(index_file,MYF(0)) < 0 && ! write_error) { write_error=1; sql_print_error(ER(ER_ERROR_ON_WRITE),name,errno); } index_file=0; } + safeFree(name); } diff --git a/sql/log_event.cc b/sql/log_event.cc index 62a3658bc9f..9e739da1c9d 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -26,84 +26,78 @@ static void pretty_print_char(FILE* file, int c) { fputc('\'', file); - switch(c) - { - case '\n': fprintf(file, "\\n"); break; - case '\r': fprintf(file, "\\r"); break; - case '\\': fprintf(file, "\\\\"); break; - case '\b': fprintf(file, "\\b"); break; - case '\'': fprintf(file, "\\'"); break; - case 0 : fprintf(file, "\\0"); break; - default: - fputc(c, file); - break; - } - fputc( '\'', file); + switch(c) { + case '\n': fprintf(file, "\\n"); break; + case '\r': fprintf(file, "\\r"); break; + case '\\': fprintf(file, "\\\\"); break; + case '\b': fprintf(file, "\\b"); break; + case '\'': fprintf(file, "\\'"); break; + case 0 : fprintf(file, "\\0"); break; + default: + fputc(c, file); + break; + } + fputc('\'', file); } -int Query_log_event::write(FILE* file) +int Query_log_event::write(IO_CACHE* file) { return query ? Log_event::write(file) : -1; } -int Log_event::write(FILE* file) +int Log_event::write(IO_CACHE* file) { - if (write_header(file) - || write_data(file) || fflush(file)) return -1; - return 0; + return (write_header(file) || write_data(file)) ? -1 : 0; } -int Log_event::write_header(FILE* file) +int Log_event::write_header(IO_CACHE* file) { - char buf[LOG_EVENT_HEADER_LEN]; // make sure to change this when the header gets bigger + char buf[LOG_EVENT_HEADER_LEN]; char* pos = buf; int4store(pos, when); // timestamp pos += 4; *pos++ = get_type_code(); // event type code int4store(pos, server_id); pos += 4; - int4store(pos, get_data_size() + LOG_EVENT_HEADER_LEN); + long tmp=get_data_size() + LOG_EVENT_HEADER_LEN; + int4store(pos, tmp); pos += 4; - return (my_fwrite(file, (byte*) buf, (uint) (pos - buf), - MYF(MY_NABP | MY_WME))); + return (my_b_write(file, (byte*) buf, (uint) (pos - buf))); } #ifndef MYSQL_CLIENT -int Log_event::read_log_event(FILE* file, String* packet, +int Log_event::read_log_event(IO_CACHE* file, String* packet, pthread_mutex_t* log_lock) { ulong data_len; char buf[LOG_EVENT_HEADER_LEN]; - if(log_lock) + if (log_lock) pthread_mutex_lock(log_lock); - if (my_fread(file, (byte*)buf, sizeof(buf), MYF(MY_NABP))) - { - if(log_lock) pthread_mutex_unlock(log_lock); - return feof(file) ? LOG_READ_EOF: LOG_READ_IO; - } + if (my_b_read(file, (byte*) buf, sizeof(buf))) + { + if (log_lock) pthread_mutex_unlock(log_lock); + return file->error >= 0 ? LOG_READ_TRUNC: LOG_READ_IO; + } data_len = uint4korr(buf + EVENT_LEN_OFFSET); if (data_len < LOG_EVENT_HEADER_LEN || data_len > MAX_EVENT_LEN) - { - if(log_lock) pthread_mutex_unlock(log_lock); - return LOG_READ_BOGUS; - } + { + if (log_lock) pthread_mutex_unlock(log_lock); + return LOG_READ_BOGUS; + } packet->append(buf, sizeof(buf)); data_len -= LOG_EVENT_HEADER_LEN; - if (!data_len) - { - if(log_lock) pthread_mutex_unlock(log_lock); - return 0; // the event does not have a data section - } - if (packet->append(file, data_len, MYF(MY_WME|MY_NABP))) + if (data_len) + { + if (packet->append(file, data_len)) { if(log_lock) pthread_mutex_unlock(log_lock); - return feof(file) ? LOG_READ_TRUNC: LOG_READ_IO; + return file->error >= 0 ? LOG_READ_TRUNC: LOG_READ_IO; } - - if(log_lock) pthread_mutex_unlock(log_lock); + } + if (log_lock) pthread_mutex_unlock(log_lock); return 0; } @@ -111,18 +105,18 @@ int Log_event::read_log_event(FILE* file, String* packet, // allocates memory - the caller is responsible for clean-up -Log_event* Log_event::read_log_event(FILE* file, pthread_mutex_t* log_lock) +Log_event* Log_event::read_log_event(IO_CACHE* file, pthread_mutex_t* log_lock) { time_t timestamp; uint32 server_id; char buf[LOG_EVENT_HEADER_LEN-4]; if(log_lock) pthread_mutex_lock(log_lock); - if (my_fread(file, (byte *) buf, sizeof(buf), MY_NABP)) - { - if(log_lock) pthread_mutex_unlock(log_lock); - return NULL; - } + if (my_b_read(file, (byte *) buf, sizeof(buf))) + { + if (log_lock) pthread_mutex_unlock(log_lock); + return NULL; + } timestamp = uint4korr(buf); server_id = uint4korr(buf + 5); @@ -132,13 +126,11 @@ Log_event* Log_event::read_log_event(FILE* file, pthread_mutex_t* log_lock) { Query_log_event* q = new Query_log_event(file, timestamp, server_id); if(log_lock) pthread_mutex_unlock(log_lock); - if (!q->query) { delete q; - return NULL; + q=NULL; } - return q; } @@ -146,13 +138,11 @@ Log_event* Log_event::read_log_event(FILE* file, pthread_mutex_t* log_lock) { Load_log_event* l = new Load_log_event(file, timestamp, server_id); if(log_lock) pthread_mutex_unlock(log_lock); - if (!l->table_name) { delete l; - return NULL; + l=NULL; } - return l; } @@ -165,9 +155,8 @@ Log_event* Log_event::read_log_event(FILE* file, pthread_mutex_t* log_lock) if (!r->new_log_ident) { delete r; - return NULL; + r=NULL; } - return r; } @@ -179,9 +168,8 @@ Log_event* Log_event::read_log_event(FILE* file, pthread_mutex_t* log_lock) if (e->type == INVALID_INT_EVENT) { delete e; - return NULL; + e=NULL; } - return e; } @@ -198,12 +186,11 @@ Log_event* Log_event::read_log_event(FILE* file, pthread_mutex_t* log_lock) return e; } default: - if(log_lock) pthread_mutex_unlock(log_lock); - return NULL; + break; } - //impossible - if(log_lock) pthread_mutex_unlock(log_lock); + // default + if (log_lock) pthread_mutex_unlock(log_lock); return NULL; } @@ -323,26 +310,24 @@ void Rotate_log_event::print(FILE* file, bool short_form) fflush(file); } -Rotate_log_event::Rotate_log_event(FILE* file, time_t when_arg, +Rotate_log_event::Rotate_log_event(IO_CACHE* file, time_t when_arg, uint32 server_id): Log_event(when_arg, 0, 0, server_id),new_log_ident(NULL),alloced(0) { char *tmp_ident; char buf[4]; - if (my_fread(file, (byte*) buf, sizeof(buf), MYF(MY_NABP | MY_WME))) + if (my_b_read(file, (byte*) buf, sizeof(buf))) return; - ulong event_len; event_len = uint4korr(buf); - if(event_len < ROTATE_EVENT_OVERHEAD) + if (event_len < ROTATE_EVENT_OVERHEAD) return; ident_len = (uchar)(event_len - ROTATE_EVENT_OVERHEAD); - if (!(tmp_ident = (char*) my_malloc((uint)ident_len, MYF(MY_WME)))) return; - if (my_fread( file, (byte*) tmp_ident, (uint)ident_len, MYF(MY_NABP | MY_WME))) + if (my_b_read( file, (byte*) tmp_ident, (uint) ident_len)) { my_free((gptr) tmp_ident, MYF(0)); return; @@ -376,21 +361,18 @@ Rotate_log_event::Rotate_log_event(const char* buf, int event_len): alloced = 1; } -int Rotate_log_event::write_data(FILE* file) +int Rotate_log_event::write_data(IO_CACHE* file) { - if (my_fwrite(file, (byte*) new_log_ident, (uint) ident_len, - MYF(MY_NABP | MY_WME))) - return -1; - return 0; + return my_b_write(file, (byte*) new_log_ident, (uint) ident_len) ? -1 :0; } -Query_log_event::Query_log_event(FILE* file, time_t when_arg, +Query_log_event::Query_log_event(IO_CACHE* file, time_t when_arg, uint32 server_id): Log_event(when_arg,0,0,server_id),data_buf(0),query(NULL),db(NULL) { char buf[QUERY_HEADER_LEN + 4]; ulong data_len; - if (my_fread(file, (byte*) buf, sizeof(buf), MYF(MY_NABP | MY_WME))) + if (my_b_read(file, (byte*) buf, sizeof(buf))) return; // query == NULL will tell the // caller there was a problem data_len = uint4korr(buf); @@ -402,9 +384,10 @@ Query_log_event::Query_log_event(FILE* file, time_t when_arg, db_len = (uint)buf[12]; error_code = uint2korr(buf + 13); + /* Allocate one byte extra for end \0 */ if (!(data_buf = (char*) my_malloc(data_len+1, MYF(MY_WME)))) return; - if (my_fread( file, (byte*) data_buf, data_len, MYF(MY_NABP | MY_WME))) + if (my_b_read( file, (byte*) data_buf, data_len)) { my_free((gptr) data_buf, MYF(0)); data_buf = 0; @@ -415,7 +398,7 @@ Query_log_event::Query_log_event(FILE* file, time_t when_arg, db = data_buf; query=data_buf + db_len + 1; q_len = data_len - 1 - db_len; - *((char*)query + q_len) = 0; + *((char*) query + q_len) = 0; // Safety } Query_log_event::Query_log_event(const char* buf, int event_len): @@ -430,7 +413,7 @@ Query_log_event::Query_log_event(const char* buf, int event_len): exec_time = uint4korr(buf + 8); error_code = uint2korr(buf + 13); - if (!(data_buf = (char*) my_malloc( data_len + 1, MYF(MY_WME)))) + if (!(data_buf = (char*) my_malloc(data_len + 1, MYF(MY_WME)))) return; memcpy(data_buf, buf + QUERY_HEADER_LEN + 4, data_len); @@ -457,9 +440,9 @@ void Query_log_event::print(FILE* file, bool short_form) fprintf(file, ";\n"); } -int Query_log_event::write_data(FILE* file) +int Query_log_event::write_data(IO_CACHE* file) { - if(!query) return -1; + if (!query) return -1; char buf[QUERY_HEADER_LEN]; char* pos = buf; @@ -471,23 +454,21 @@ int Query_log_event::write_data(FILE* file) int2store(pos, error_code); pos += 2; - if (my_fwrite(file, (byte*) buf, (uint)(pos - buf), MYF(MY_NABP | MY_WME)) || - my_fwrite(file, (db) ? (byte*) db : (byte*)"", - db_len + 1, MYF(MY_NABP | MY_WME)) || - my_fwrite(file, (byte*) query, q_len, MYF(MY_NABP | MY_WME))) - return -1; - return 0; + return (my_b_write(file, (byte*) buf, (uint)(pos - buf)) || + my_b_write(file, (db) ? (byte*) db : (byte*)"", db_len + 1) || + my_b_write(file, (byte*) query, q_len)) ? -1 : 0; } -Intvar_log_event:: Intvar_log_event(FILE* file, time_t when_arg, +Intvar_log_event:: Intvar_log_event(IO_CACHE* file, time_t when_arg, uint32 server_id) :Log_event(when_arg,0,0,server_id), type(INVALID_INT_EVENT) { - my_fseek(file, 4L, MY_SEEK_CUR, MYF(MY_WME)); // skip the event length - char buf[9]; - if(my_fread(file, (byte*)buf, sizeof(buf), MYF(MY_NABP|MY_WME))) return; - type = buf[0]; - val = uint8korr(buf+1); + char buf[9+4]; + if (!my_b_read(file, (byte*) buf, sizeof(buf))) + { + type = buf[4]; + val = uint8korr(buf+1+4); + } } Intvar_log_event::Intvar_log_event(const char* buf):Log_event(buf) @@ -497,12 +478,12 @@ Intvar_log_event::Intvar_log_event(const char* buf):Log_event(buf) val = uint8korr(buf+1); } -int Intvar_log_event::write_data(FILE* file) +int Intvar_log_event::write_data(IO_CACHE* file) { char buf[9]; buf[0] = type; int8store(buf + 1, val); - return my_fwrite(file, (byte*) buf, sizeof(buf), MYF(MY_NABP|MY_WME)); + return my_b_write(file, (byte*) buf, sizeof(buf)); } void Intvar_log_event::print(FILE* file, bool short_form) @@ -529,7 +510,7 @@ void Intvar_log_event::print(FILE* file, bool short_form) } -int Load_log_event::write_data(FILE* file __attribute__((unused))) +int Load_log_event::write_data(IO_CACHE* file) { char buf[LOAD_HEADER_LEN]; int4store(buf, thread_id); @@ -539,77 +520,46 @@ int Load_log_event::write_data(FILE* file __attribute__((unused))) buf[13] = (char)db_len; int4store(buf + 14, num_fields); - if(my_fwrite(file, (byte*)buf, sizeof(buf), MYF(MY_NABP|MY_WME)) || - my_fwrite(file, (byte*)&sql_ex, sizeof(sql_ex), MYF(MY_NABP|MY_WME))) + if(my_b_write(file, (byte*)buf, sizeof(buf)) || + my_b_write(file, (byte*)&sql_ex, sizeof(sql_ex))) return 1; - if(num_fields && fields && field_lens) - { - if(my_fwrite(file, (byte*)field_lens, num_fields, MYF(MY_NABP|MY_WME)) || - my_fwrite(file, (byte*)fields, field_block_len, MYF(MY_NABP|MY_WME))) - return 1; - } - - if(my_fwrite(file, (byte*)table_name, table_name_len + 1, MYF(MY_NABP|MY_WME)) || - my_fwrite(file, (byte*)db, db_len + 1, MYF(MY_NABP|MY_WME)) || - my_fwrite(file, (byte*)fname, fname_len, MYF(MY_NABP|MY_WME)) ) + if (num_fields && fields && field_lens) + { + if(my_b_write(file, (byte*)field_lens, num_fields) || + my_b_write(file, (byte*)fields, field_block_len)) + return 1; + } + if(my_b_write(file, (byte*)table_name, table_name_len + 1) || + my_b_write(file, (byte*)db, db_len + 1) || + my_b_write(file, (byte*)fname, fname_len)) return 1; - - return 0; } -Load_log_event::Load_log_event(FILE* file, time_t when, uint32 server_id): +Load_log_event::Load_log_event(IO_CACHE* file, time_t when, uint32 server_id): Log_event(when,0,0,server_id),data_buf(0),num_fields(0), fields(0),field_lens(0),field_block_len(0), table_name(0),db(0),fname(0) - { char buf[LOAD_HEADER_LEN + 4]; ulong data_len; - if(my_fread(file, (byte*)buf, sizeof(buf), MYF(MY_NABP|MY_WME)) || - my_fread(file, (byte*)&sql_ex, sizeof(sql_ex), MYF(MY_NABP|MY_WME))) - return; - - data_len = uint4korr(buf); - thread_id = uint4korr(buf+4); - exec_time = uint4korr(buf+8); - skip_lines = uint4korr(buf + 12); - table_name_len = (uint)buf[16]; - db_len = (uint)buf[17]; - num_fields = uint4korr(buf + 18); - - data_len -= LOAD_EVENT_OVERHEAD; - if(!(data_buf = (char*)my_malloc(data_len + 1, MYF(MY_WME)))) + if (my_b_read(file, (byte*)buf, sizeof(buf)) || + my_b_read(file, (byte*)&sql_ex, sizeof(sql_ex))) return; - if(my_fread(file, (byte*)data_buf, data_len, MYF(MY_NABP|MY_WME))) + data_len = uint4korr(buf) - LOAD_EVENT_OVERHEAD; + if (!(data_buf = (char*)my_malloc(data_len + 1, MYF(MY_WME)))) return; - - if(num_fields > data_len) // simple sanity check against corruption + if (my_b_read(file, (byte*)data_buf, data_len)) return; - - field_lens = (uchar*)data_buf; - - uint i; - for(i = 0; i < num_fields; i++) - { - field_block_len += (uint)field_lens[i] + 1; - } - fields = (char*)field_lens + num_fields; - - *((char*)data_buf+data_len) = 0; - table_name = fields + field_block_len; - db = table_name + table_name_len + 1; - fname = db + db_len + 1; - fname_len = data_len - 2 - db_len - table_name_len - num_fields - field_block_len; + copy_log_event(buf,data_len); } Load_log_event::Load_log_event(const char* buf, int event_len): Log_event(when,0,0,server_id),data_buf(0),num_fields(0),fields(0), field_lens(0),field_block_len(0), table_name(0),db(0),fname(0) - { ulong data_len; @@ -617,9 +567,16 @@ Load_log_event::Load_log_event(const char* buf, int event_len): return; buf += EVENT_LEN_OFFSET; - data_len = event_len; + if(!(data_buf = (char*)my_malloc(data_len + 1, MYF(MY_WME)))) + return; + memcpy(data_buf, buf + 22 + sizeof(sql_ex), data_len); + copy_log_event(buf, data_len); +} + +void Load_log_event::copy_log_event(const char *buf, ulong data_len) +{ thread_id = uint4korr(buf+4); exec_time = uint4korr(buf+8); skip_lines = uint4korr(buf + 12); @@ -627,32 +584,23 @@ Load_log_event::Load_log_event(const char* buf, int event_len): db_len = (uint)buf[17]; num_fields = uint4korr(buf + 18); - data_len -= LOAD_EVENT_OVERHEAD; - memcpy(&sql_ex, buf + 22, sizeof(sql_ex)); - - if(!(data_buf = (char*)my_malloc(data_len + 1, MYF(MY_WME)))) + if (num_fields > data_len) // simple sanity check against corruption return; - memcpy(data_buf, buf + 22 + sizeof(sql_ex), data_len); - - if(num_fields > data_len) // simple sanity check against corruption - return; - - field_lens = (uchar*)data_buf; - + field_lens = (uchar*) data_buf; uint i; - for(i = 0; i < num_fields; i++) - { - field_block_len += (uint)field_lens[i] + 1; - } + for (i = 0; i < num_fields; i++) + { + field_block_len += (uint)field_lens[i] + 1; + } fields = (char*)field_lens + num_fields; *((char*)data_buf+data_len) = 0; table_name = fields + field_block_len; db = table_name + table_name_len + 1; fname = db + db_len + 1; - fname_len = data_len - 2 - db_len - table_name_len - num_fields - field_block_len; - + fname_len = data_len - 2 - db_len - table_name_len - num_fields - + field_block_len; } @@ -711,21 +659,21 @@ void Load_log_event::print(FILE* file, bool short_form) if((int)skip_lines > 0) fprintf(file, " IGNORE %ld LINES ", skip_lines); - if(num_fields) + if (num_fields) + { + uint i; + const char* field = fields; + fprintf( file, " ("); + for(i = 0; i < num_fields; i++) { - uint i; - const char* field = fields; - fprintf( file, " ("); - for(i = 0; i < num_fields; i++) - { - if(i) - fputc(',', file); - fprintf(file, field); + if(i) + fputc(',', file); + fprintf(file, field); - field += field_lens[i] + 1; - } - fputc(')', file); + field += field_lens[i] + 1; } + fputc(')', file); + } fprintf(file, ";\n"); } diff --git a/sql/log_event.h b/sql/log_event.h index 33fcab4fea9..3a571c0f9a4 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -65,9 +65,9 @@ public: int valid_exec_time; // if false, the exec time setting is bogus uint32 server_id; - int write(FILE* file); - int write_header(FILE* file); - virtual int write_data(FILE* file __attribute__((unused))) { return 0; } + int write(IO_CACHE* file); + int write_header(IO_CACHE* file); + virtual int write_data(IO_CACHE* file __attribute__((unused))) { return 0; } virtual Log_event_type get_type_code() = 0; Log_event(time_t when_arg, ulong exec_time_arg = 0, int valid_exec_time_arg = 0, uint32 server_id = 0): when(when_arg), @@ -92,11 +92,11 @@ public: void print_header(FILE* file); // if mutex is 0, the read will proceed without mutex - static Log_event* read_log_event(FILE* file, pthread_mutex_t* log_lock); + static Log_event* read_log_event(IO_CACHE* file, pthread_mutex_t* log_lock); static Log_event* read_log_event(const char* buf, int event_len); #ifndef MYSQL_CLIENT - static int read_log_event(FILE* file, String* packet, + static int read_log_event(IO_CACHE* file, String* packet, pthread_mutex_t* log_lock); #endif @@ -132,18 +132,18 @@ public: } #endif - Query_log_event(FILE* file, time_t when, uint32 server_id); + Query_log_event(IO_CACHE* file, time_t when, uint32 server_id); Query_log_event(const char* buf, int event_len); ~Query_log_event() { if (data_buf) { - my_free((gptr)data_buf, MYF(0)); + my_free((gptr) data_buf, MYF(0)); } } Log_event_type get_type_code() { return QUERY_EVENT; } - int write(FILE* file); - int write_data(FILE* file); // returns 0 on success, -1 on error + int write(IO_CACHE* file); + int write_data(IO_CACHE* file); // returns 0 on success, -1 on error int get_data_size() { return q_len + db_len + 2 + @@ -183,6 +183,8 @@ class Load_log_event: public Log_event { protected: char* data_buf; + void Load_log_event::copy_log_event(const char *buf, ulong data_len); + public: int thread_id; uint32 table_name_len; @@ -272,17 +274,17 @@ public: void set_fields(List<Item> &fields); #endif - Load_log_event(FILE* file, time_t when, uint32 server_id); + Load_log_event(IO_CACHE * file, time_t when, uint32 server_id); Load_log_event(const char* buf, int event_len); ~Load_log_event() { if (data_buf) { - my_free((gptr)data_buf, MYF(0)); + my_free((gptr) data_buf, MYF(0)); } } Log_event_type get_type_code() { return LOAD_EVENT; } - int write_data(FILE* file); // returns 0 on success, -1 on error + int write_data(IO_CACHE* file); // returns 0 on success, -1 on error int get_data_size() { return table_name_len + 2 + db_len + 2 + fname_len @@ -311,30 +313,26 @@ public: created = (uint32) when; memcpy(server_version, ::server_version, sizeof(server_version)); } - Start_log_event(FILE* file, time_t when_arg, uint32 server_id) : + Start_log_event(IO_CACHE* file, time_t when_arg, uint32 server_id) : Log_event(when_arg, 0, 0, server_id) { char buf[sizeof(server_version) + sizeof(binlog_version) + - sizeof(created)]; - my_fseek(file, 4L, MY_SEEK_CUR, MYF(MY_WME)); // skip the event length - if (my_fread(file, (byte*) buf, sizeof(buf), MYF(MY_NABP | MY_WME))) + sizeof(created)+4]; + if (my_b_read(file, (byte*) buf, sizeof(buf))) return; - binlog_version = uint2korr(buf); - memcpy(server_version, buf + 2, sizeof(server_version)); - created = uint4korr(buf + 2 + sizeof(server_version)); + binlog_version = uint2korr(buf+4); + memcpy(server_version, buf + 6, sizeof(server_version)); + created = uint4korr(buf + 6 + sizeof(server_version)); } Start_log_event(const char* buf); ~Start_log_event() {} Log_event_type get_type_code() { return START_EVENT;} - int write_data(FILE* file) + int write_data(IO_CACHE* file) { - if(my_fwrite(file, (byte*) &binlog_version, sizeof(binlog_version), - MYF(MY_NABP | MY_WME)) || - my_fwrite(file, (byte*) server_version, sizeof(server_version), - MYF(MY_NABP | MY_WME)) || - my_fwrite(file, (byte*) &created, sizeof(created), - MYF(MY_NABP | MY_WME))) + if (my_b_write(file, (byte*) &binlog_version, sizeof(binlog_version)) || + my_b_write(file, (byte*) server_version, sizeof(server_version)) || + my_b_write(file, (byte*) &created, sizeof(created))) return -1; return 0; } @@ -354,12 +352,12 @@ public: Intvar_log_event(uchar type_arg, ulonglong val_arg) :Log_event(time(NULL)),val(val_arg),type(type_arg) {} - Intvar_log_event(FILE* file, time_t when, uint32 server_id); + Intvar_log_event(IO_CACHE* file, time_t when, uint32 server_id); Intvar_log_event(const char* buf); ~Intvar_log_event() {} Log_event_type get_type_code() { return INTVAR_EVENT;} int get_data_size() { return sizeof(type) + sizeof(val);} - int write_data(FILE* file); + int write_data(IO_CACHE* file); void print(FILE* file, bool short_form = 0); @@ -370,10 +368,11 @@ class Stop_log_event: public Log_event public: Stop_log_event() :Log_event(time(NULL)) {} - Stop_log_event(FILE* file, time_t when_arg, uint32 server_id): + Stop_log_event(IO_CACHE* file, time_t when_arg, uint32 server_id): Log_event(when_arg,0,0,server_id) { - my_fseek(file, 4L, MY_SEEK_CUR, MYF(MY_WME)); // skip the event length + char skip[4]; + my_b_read(file, skip, sizeof(skip)); // skip the event length } Stop_log_event(const char* buf):Log_event(buf) { @@ -397,7 +396,7 @@ public: alloced(0) {} - Rotate_log_event(FILE* file, time_t when, uint32 server_id) ; + Rotate_log_event(IO_CACHE* file, time_t when, uint32 server_id) ; Rotate_log_event(const char* buf, int event_len); ~Rotate_log_event() { @@ -406,7 +405,7 @@ public: } Log_event_type get_type_code() { return ROTATE_EVENT;} int get_data_size() { return ident_len;} - int write_data(FILE* file); + int write_data(IO_CACHE* file); void print(FILE* file, bool short_form = 0); }; diff --git a/sql/mf_iocache.cc b/sql/mf_iocache.cc index 49df40adaf6..47c00a8ac00 100644 --- a/sql/mf_iocache.cc +++ b/sql/mf_iocache.cc @@ -32,17 +32,19 @@ #define MAP_TO_USE_RAID #include "mysql_priv.h" -#include <mysys_err.h> #ifdef HAVE_AIOWAIT +#include <mysys_err.h> #include <errno.h> static void my_aiowait(my_aio_result *result); #endif - /* if cachesize == 0 then use default cachesize (from s-file) */ - /* returns 0 if we have enough memory */ - extern "C" { + /* + ** if cachesize == 0 then use default cachesize (from s-file) + ** if file == -1 then real_open_cached_file() will be called. + ** returns 0 if ok + */ int init_io_cache(IO_CACHE *info, File file, uint cachesize, enum cache_type type, my_off_t seek_offset, @@ -60,20 +62,26 @@ int init_io_cache(IO_CACHE *info, File file, uint cachesize, min_cache=use_async_io ? IO_SIZE*4 : IO_SIZE*2; if (type == READ_CACHE) { /* Assume file isn't growing */ - my_off_t file_pos,end_of_file; - if ((file_pos=my_tell(file,MYF(0)) == MY_FILEPOS_ERROR)) - DBUG_RETURN(1); - end_of_file=my_seek(file,0L,MY_SEEK_END,MYF(0)); - if (end_of_file < seek_offset) - end_of_file=seek_offset; - VOID(my_seek(file,file_pos,MY_SEEK_SET,MYF(0))); - if ((my_off_t) cachesize > end_of_file-seek_offset+IO_SIZE*2-1) + if (cache_myflags & MY_DONT_CHECK_FILESIZE) + { + cache_myflags &= ~MY_DONT_CHECK_FILESIZE; + } + else { - cachesize=(uint) (end_of_file-seek_offset)+IO_SIZE*2-1; - use_async_io=0; /* No nead to use async */ + my_off_t file_pos,end_of_file; + if ((file_pos=my_tell(file,MYF(0)) == MY_FILEPOS_ERROR)) + DBUG_RETURN(1); + end_of_file=my_seek(file,0L,MY_SEEK_END,MYF(0)); + if (end_of_file < seek_offset) + end_of_file=seek_offset; + VOID(my_seek(file,file_pos,MY_SEEK_SET,MYF(0))); + if ((my_off_t) cachesize > end_of_file-seek_offset+IO_SIZE*2-1) + { + cachesize=(uint) (end_of_file-seek_offset)+IO_SIZE*2-1; + use_async_io=0; /* No nead to use async */ + } } } - if ((int) type < (int) READ_NET) { for (;;) @@ -167,7 +175,8 @@ my_bool reinit_io_cache(IO_CACHE *info, enum cache_type type, DBUG_ENTER("reinit_io_cache"); info->seek_not_done= test(info->file >= 0); /* Seek not done */ - if (!clear_cache && seek_offset >= info->pos_in_file && + if (! clear_cache && + seek_offset >= info->pos_in_file && seek_offset <= info->pos_in_file + (uint) (info->rc_end - info->rc_request_pos)) { /* use current buffer */ @@ -231,6 +240,7 @@ int _my_b_read(register IO_CACHE *info, byte *Buffer, uint Count) { uint length,diff_length,left_length; my_off_t max_length, pos_in_file; + memcpy(Buffer,info->rc_pos, (size_t) (left_length=(uint) (info->rc_end-info->rc_pos))); Buffer+=left_length; @@ -607,7 +617,9 @@ int flush_io_cache(IO_CACHE *info) length=(uint) (info->rc_pos - info->buffer); if (info->seek_not_done) { /* File touched, do seek */ - VOID(my_seek(info->file,info->pos_in_file,MY_SEEK_SET,MYF(0))); + if (my_seek(info->file,info->pos_in_file,MY_SEEK_SET,MYF(0)) == + MY_FILEPOS_ERROR) + DBUG_RETURN((info->error= -1)); info->seek_not_done=0; } info->rc_pos=info->buffer; @@ -644,4 +656,4 @@ int end_io_cache(IO_CACHE *info) DBUG_RETURN(error); } /* end_io_cache */ -} +} /* extern "C" */ diff --git a/sql/mysqlbinlog.cc b/sql/mysqlbinlog.cc index 3756d8bf712..6c543d0bbf6 100644 --- a/sql/mysqlbinlog.cc +++ b/sql/mysqlbinlog.cc @@ -55,7 +55,7 @@ static struct option long_options[] = {"password", required_argument,0, 'p'}, {"position", required_argument,0, 'j'}, #ifndef DBUG_OFF - {"debug", required_argument, 0, '#'} + {"debug", optional_argument, 0, '#'} #endif }; @@ -151,7 +151,7 @@ static int parse_args(int *argc, char*** argv) { int c, opt_index = 0; - while((c = getopt_long(*argc, *argv, "so:#:h:j:u:p:P:t:?", long_options, + while((c = getopt_long(*argc, *argv, "so:#::h:j:u:p:P:t:?", long_options, &opt_index)) != EOF) { switch(c) @@ -310,86 +310,106 @@ Unfortunately, no sweepstakes today, adjusted position to 4\n"); static void dump_local_log_entries(const char* logname) { - FILE* file; - int rec_count = 0; - - if(logname && logname[0] != '-') - file = my_fopen(logname, O_RDONLY|O_BINARY, MYF(MY_WME)); - else - file = stdin; - - if(!file) - die("Could not open log file %s", logname); - - if(my_fseek(file, position, MY_SEEK_SET, MYF(MY_WME)) == MY_FILEPOS_ERROR) - die("failed on my_fseek()"); - - if(!position) - { - char magic[4]; - if (my_fread(file, (byte*) magic, sizeof(magic), MYF(MY_NABP|MY_WME))) - die("I/O error reading binlog magic number"); - if(memcmp(magic, BINLOG_MAGIC, 4)) - die("Bad magic number"); + File fd; + IO_CACHE cache,*file= &cache; + int rec_count = 0; + + if (logname && logname[0] != '-') + { + if ((fd = my_open(logname, O_RDONLY | O_BINARY, MYF(MY_WME))) < 0) + exit(1); + if (init_io_cache(file, fd, 0, READ_CACHE, (my_off_t) position, 0, + MYF(MY_WME | MY_NABP))) + exit(1); + } + else + { + if (init_io_cache(file, fileno(stdout), 0, READ_CACHE, (my_off_t) 0, + 0, MYF(MY_WME | MY_NABP | MY_DONT_CHECK_FILESIZE))) + exit(1); + if (position) + { + /* skip 'position' characters from stdout */ + char buff[IO_SIZE]; + my_off_t length,tmp; + for (length=position ; length > 0 ; length-=tmp) + { + tmp=min(length,sizeof(buff)); + if (my_b_read(file,buff,tmp)) + exit(1); + } + } + file->pos_in_file=position; + file->seek_not_done=0; + } + + if (!position) + { + char magic[4]; + if (my_b_read(file, (byte*) magic, sizeof(magic))) + die("I/O error reading binlog magic number"); + if(memcmp(magic, BINLOG_MAGIC, 4)) + die("Bad magic number"); } - while(1) - { - Log_event* ev = Log_event::read_log_event(file, 0); - if(!ev) - if(!feof(file)) + while(1) + { + Log_event* ev = Log_event::read_log_event(file, 0); + if (!ev) + { + if (file->error) die("Could not read entry at offset %ld : Error in log format or \ read error", - my_ftell(file, MYF(MY_WME))); - else - break; - - if(rec_count >= offset) - ev->print(stdout, short_form); - rec_count++; - delete ev; - } - - my_fclose(file, MYF(MY_WME)); + my_b_tell(file)); + break; + } + if (rec_count >= offset) + ev->print(stdout, short_form); + rec_count++; + delete ev; + } + my_close(fd, MYF(MY_WME)); + end_io_cache(file); } + int main(int argc, char** argv) { MY_INIT(argv[0]); parse_args(&argc, (char***)&argv); if(!argc && !table) - { - usage(); - return -1; - } + { + usage(); + return -1; + } if(use_remote) - { - init_thr_alarm(10); // need to do this manually - mysql = safe_connect(); - } + { + init_thr_alarm(10); // need to do this manually + mysql = safe_connect(); + } - if(table) - { - if(!use_remote) - die("You must specify connection parameter to get table dump"); - char* db = (char*)table; - char* tbl = (char*) strchr(table, '.'); - if(!tbl) - die("You must use database.table syntax to specify the table"); - *tbl++ = 0; - dump_remote_table(&mysql->net, db, tbl); - } + if (table) + { + if(!use_remote) + die("You must specify connection parameter to get table dump"); + char* db = (char*)table; + char* tbl = (char*) strchr(table, '.'); + if(!tbl) + die("You must use database.table syntax to specify the table"); + *tbl++ = 0; + dump_remote_table(&mysql->net, db, tbl); + } else - while(--argc >= 0) + { + while(--argc >= 0) { dump_log_entries(*(argv++)); } - - if(use_remote) + } + if (use_remote) mc_mysql_close(mysql); - return 0; } diff --git a/sql/mysqld.cc b/sql/mysqld.cc index e9389727e9a..db67eb1f6ea 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -131,7 +131,7 @@ extern "C" int gethostname(char *name, int namelen); #ifndef DBUG_OFF static const char* default_dbug_option=IF_WIN("d:t:i:O,\\mysqld.trace", - "d:t:i:o,/tmp/mysqld.trace"); + "d:t:i:o,/tmp/mysqld.trace"); #endif #ifdef __NT__ @@ -157,7 +157,7 @@ static pthread_t select_thread; static pthread_t flush_thread; // Used when debugging static bool opt_log,opt_update_log,opt_bin_log,opt_slow_log,opt_noacl, opt_disable_networking=0, opt_bootstrap=0,opt_skip_show_db=0, - opt_ansi_mode=0,opt_myisam_log=0; + opt_ansi_mode=0,opt_myisam_log=0, opt_large_files=sizeof(my_off_t) > 4; bool opt_sql_bin_update = 0, opt_log_slave_updates = 0; extern MASTER_INFO glob_mi; extern int init_master_info(MASTER_INFO* mi); @@ -579,8 +579,8 @@ void unireg_abort(int exit_code) { if (exit_code) sql_print_error("Aborting\n"); - (void) my_delete(pidfile_name,MYF(0)); // This may not always exist clean_up(); /* purecov: inspected */ + (void) my_delete(pidfile_name,MYF(0)); // This may not always exist exit(exit_code); /* purecov: inspected */ } @@ -2436,20 +2436,21 @@ struct show_var_st init_vars[]= { #endif {"character_set", default_charset, SHOW_CHAR}, {"character_sets", (char*) &charsets_list, SHOW_CHAR_PTR}, - {"connect_timeout", (char*) &connect_timeout, SHOW_LONG}, {"concurrent_insert", (char*) &myisam_concurrent_insert, SHOW_MY_BOOL}, + {"connect_timeout", (char*) &connect_timeout, SHOW_LONG}, {"datadir", mysql_real_data_home, SHOW_CHAR}, {"delay_key_write", (char*) &myisam_delay_key_write, SHOW_MY_BOOL}, {"delayed_insert_limit", (char*) &delayed_insert_limit, SHOW_LONG}, {"delayed_insert_timeout", (char*) &delayed_insert_timeout, SHOW_LONG}, {"delayed_queue_size", (char*) &delayed_queue_size, SHOW_LONG}, - {"join_buffer_size", (char*) &join_buff_size, SHOW_LONG}, {"flush", (char*) &myisam_flush, SHOW_MY_BOOL}, {"flush_time", (char*) &flush_time, SHOW_LONG}, {"init_file", (char*) &opt_init_file, SHOW_CHAR_PTR}, {"interactive_timeout", (char*) &net_interactive_timeout, SHOW_LONG}, + {"join_buffer_size", (char*) &join_buff_size, SHOW_LONG}, {"key_buffer_size", (char*) &keybuff_size, SHOW_LONG}, {"language", language, SHOW_CHAR}, + {"large_files_support", (char*) &opt_large_files, SHOW_BOOL}, #ifdef HAVE_MLOCKALL {"locked_in_memory", (char*) &locked_in_memory, SHOW_BOOL}, #endif @@ -2472,12 +2473,15 @@ struct show_var_st init_vars[]= { {"myisam_recover_options", (char*) &myisam_recover_options_str, SHOW_CHAR_PTR}, {"myisam_sort_buffer_size", (char*) &myisam_sort_buffer_size, SHOW_LONG}, {"net_buffer_length", (char*) &net_buffer_length, SHOW_LONG}, + {"net_read_timeout", (char*) &net_read_timeout, SHOW_LONG}, {"net_retry_count", (char*) &mysqld_net_retry_count, SHOW_LONG}, + {"net_write_timeout", (char*) &net_write_timeout, SHOW_LONG}, {"pid_file", (char*) pidfile_name, SHOW_CHAR}, {"port", (char*) &mysql_port, SHOW_INT}, {"protocol_version", (char*) &protocol_version, SHOW_INT}, {"record_buffer", (char*) &my_default_record_cache_size,SHOW_LONG}, - {"server_id", (char*) &server_id, SHOW_LONG}, + {"query_buffer_size", (char*) &query_buff_size, SHOW_LONG}, + {"server_id", (char*) &server_id, SHOW_LONG}, {"skip_locking", (char*) &my_disable_locking, SHOW_MY_BOOL}, {"skip_networking", (char*) &opt_disable_networking, SHOW_BOOL}, {"skip_show_database", (char*) &opt_skip_show_db, SHOW_BOOL}, @@ -2486,11 +2490,11 @@ struct show_var_st init_vars[]= { {"sort_buffer", (char*) &sortbuff_size, SHOW_LONG}, {"table_cache", (char*) &table_cache_size, SHOW_LONG}, {"table_type", (char*) &default_table_type_name, SHOW_CHAR_PTR}, + {"thread_cache_size", (char*) &thread_cache_size, SHOW_LONG}, #ifdef HAVE_THR_SETCONCURRENCY {"thread_concurrency", (char*) &concurrency, SHOW_LONG}, #endif {"thread_stack", (char*) &thread_stack, SHOW_LONG}, - {"thread_cache_size", (char*) &thread_cache_size, SHOW_LONG}, #ifdef HAVE_TZNAME {"timezone", time_zone, SHOW_CHAR}, #endif @@ -3414,7 +3418,7 @@ static int get_service_parameters() else if ( lstrcmp(szKeyValueName, TEXT("ShowDatabase")) == 0 ) { CHECK_KEY_TYPE( REG_DWORD, szKeyValueName ); - opt_disable_networking = !(*lpdwValue); + opt_skip_show_db = !(*lpdwValue); } else if ( lstrcmp(szKeyValueName, TEXT("HostnameCaching")) == 0 ) { diff --git a/sql/net_pkg.cc b/sql/net_pkg.cc index 2308aa40d52..d412b71b363 100644 --- a/sql/net_pkg.cc +++ b/sql/net_pkg.cc @@ -319,11 +319,11 @@ bool net_store_data(String* packet, I_List<i_string>* str_list) i_string* s; while((s=it++)) - { - if(tmp.length()) - tmp.append(','); - tmp.append(s->ptr); - } + { + if(tmp.length()) + tmp.append(','); + tmp.append(s->ptr); + } return net_store_data(packet, (char*)tmp.ptr(), tmp.length()); } diff --git a/sql/sql_class.cc b/sql/sql_class.cc index f86c0cf7461..cd685cb3437 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -114,11 +114,17 @@ THD::THD() ull=0; system_thread=0; bzero((char*) &mem_root,sizeof(mem_root)); +#if defined(HAVE_BDB) || defined(HAVE_INNOBASE) || defined(HAVE_GEMENI) + if (open_cached_file(&transactions.trans_log, + mysql_tempdir,LOG_PREFIX,0,MYF(MY_WME))) + killed=1; + transaction.bdb_lock_count=0; +#endif + transaction.bdb_tid=0; + #ifdef __WIN__ real_id = 0 ; #endif - transaction.bdb_lock_count=0; - transaction.bdb_tid=0; } THD::~THD() @@ -137,6 +143,9 @@ THD::~THD() close_thread_tables(this); } close_temporary_tables(this); +#if defined(HAVE_BDB) || defined(HAVE_INNOBASE) || defined(HAVE_GEMENI) + close_cached_file(transactions.trans_log); +#endif if (global_read_lock) { pthread_mutex_lock(&LOCK_open); diff --git a/sql/sql_class.h b/sql/sql_class.h index e53ce950c1f..2af98d6fbf0 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -52,16 +52,16 @@ typedef struct st_log_info class MYSQL_LOG { - public: private: pthread_mutex_t LOCK_log, LOCK_index; - FILE *file, *index_file; time_t last_time,query_start; + IO_CACHE log_file; + File index_file; char *name; - enum_log_type log_type; + volatile enum_log_type log_type; char time_buff[20],db[NAME_LEN+1]; char log_file_name[FN_REFLEN],index_file_name[FN_REFLEN]; - bool write_error,inited; + bool write_error,inited,opened; bool no_rotate; // for binlog - if log name can never change // we should not try to rotate it or write any rotation events // the user should use FLUSH MASTER instead of FLUSH LOGS for @@ -85,7 +85,6 @@ public: void make_log_name(char* buf, const char* log_ident); bool is_active(const char* log_file_name); int purge_logs(THD* thd, const char* to_log); - void flush(void); void close(bool exiting = 0); // if we are exiting, we also want to close the // index file @@ -244,6 +243,7 @@ public: thr_lock_type update_lock_default; delayed_insert *di; struct st_transactions { + IO_CACHE trans_log; void *bdb_tid; uint bdb_lock_count; } transaction; diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 7195caca176..b552479bfe2 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -571,7 +571,7 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list) thread_count++; pthread_mutex_unlock(&LOCK_thread_count); if (!(tmp->thd.db=my_strdup(table_list->db,MYF(MY_WME))) || - !(tmp->thd.query=my_strdup(table_list->real_name,MYF(MY_FAE)))) + !(tmp->thd.query=my_strdup(table_list->real_name,MYF(MY_WME)))) { delete tmp; thd->fatal_error=1; @@ -1325,7 +1325,8 @@ bool select_create::send_eof() { VOID(pthread_mutex_lock(&LOCK_open)); mysql_unlock_tables(thd, lock); - hash_delete(&open_cache,(byte*) table); + if (!table->tmp_table) + hash_delete(&open_cache,(byte*) table); lock=0; table=0; VOID(pthread_mutex_unlock(&LOCK_open)); } @@ -1343,7 +1344,8 @@ void select_create::abort() if (table) { enum db_type table_type=table->db_type; - hash_delete(&open_cache,(byte*) table); + if (!table->tmp_table) + hash_delete(&open_cache,(byte*) table); quick_rm_table(table_type,db,name); table=0; } diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 674da73ba5d..dd7e1cf7b30 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -34,19 +34,23 @@ class LEX_COLUMN; #endif enum enum_sql_command { - SQLCOM_SELECT,SQLCOM_CREATE_TABLE,SQLCOM_CREATE_INDEX,SQLCOM_ALTER_TABLE, - SQLCOM_UPDATE,SQLCOM_INSERT,SQLCOM_INSERT_SELECT,SQLCOM_DELETE, - SQLCOM_DROP_TABLE,SQLCOM_DROP_INDEX,SQLCOM_SHOW_DATABASES, - SQLCOM_SHOW_TABLES,SQLCOM_SHOW_FIELDS,SQLCOM_SHOW_KEYS, + SQLCOM_SELECT, SQLCOM_CREATE_TABLE, SQLCOM_CREATE_INDEX, SQLCOM_ALTER_TABLE, + SQLCOM_UPDATE, SQLCOM_INSERT, SQLCOM_INSERT_SELECT, + SQLCOM_DELETE, SQLCOM_TRUNCATE, SQLCOM_DROP_TABLE, SQLCOM_DROP_INDEX, + + SQLCOM_SHOW_DATABASES, SQLCOM_SHOW_TABLES, SQLCOM_SHOW_FIELDS, + SQLCOM_SHOW_KEYS, SQLCOM_SHOW_VARIABLES, SQLCOM_SHOW_STATUS, + SQLCOM_SHOW_PROCESSLIST, SQLCOM_SHOW_MASTER_STAT, SQLCOM_SHOW_SLAVE_STAT, + SQLCOM_SHOW_GRANTS, SQLCOM_SHOW_CREATE, + SQLCOM_LOAD,SQLCOM_SET_OPTION,SQLCOM_LOCK_TABLES,SQLCOM_UNLOCK_TABLES, SQLCOM_GRANT, SQLCOM_CHANGE_DB, SQLCOM_CREATE_DB, SQLCOM_DROP_DB, - SQLCOM_REPAIR, SQLCOM_REPLACE, SQLCOM_REPLACE_SELECT, SQLCOM_SHOW_VARIABLES, - SQLCOM_SHOW_STATUS, SQLCOM_CREATE_FUNCTION, SQLCOM_DROP_FUNCTION, - SQLCOM_SHOW_PROCESSLIST,SQLCOM_REVOKE,SQLCOM_OPTIMIZE, SQLCOM_CHECK, - SQLCOM_FLUSH, SQLCOM_KILL, SQLCOM_SHOW_GRANTS, SQLCOM_ANALYZE, + SQLCOM_REPAIR, SQLCOM_REPLACE, SQLCOM_REPLACE_SELECT, + SQLCOM_CREATE_FUNCTION, SQLCOM_DROP_FUNCTION, + SQLCOM_REVOKE,SQLCOM_OPTIMIZE, SQLCOM_CHECK, + SQLCOM_FLUSH, SQLCOM_KILL, SQLCOM_ANALYZE, SQLCOM_ROLLBACK, SQLCOM_COMMIT, SQLCOM_SLAVE_START, SQLCOM_SLAVE_STOP, - SQLCOM_BEGIN, SQLCOM_LOAD_MASTER_TABLE, SQLCOM_SHOW_CREATE, - SQLCOM_SHOW_MASTER_STAT, SQLCOM_SHOW_SLAVE_STAT, SQLCOM_CHANGE_MASTER, + SQLCOM_BEGIN, SQLCOM_LOAD_MASTER_TABLE, SQLCOM_CHANGE_MASTER, SQLCOM_RENAME_TABLE, SQLCOM_BACKUP_TABLE, SQLCOM_RESTORE_TABLE, SQLCOM_RESET, SQLCOM_PURGE, SQLCOM_SHOW_BINLOGS }; diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 633855a18fa..9bf3346e61d 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -158,7 +158,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, unpack_filename(name,ex->file_name); #ifndef __WIN__ MY_STAT stat_info; - if (!my_stat(name,&stat_info,MYF(MY_FAE))) + if (!my_stat(name,&stat_info,MYF(MY_WME))) DBUG_RETURN(-1); // the file must be: diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 066885ef30a..b12bdcb4d98 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -71,6 +71,20 @@ static void init_signals(void) } #endif +static inline bool end_active_trans(THD *thd) +{ + if (!(thd->options & OPTION_AUTO_COMMIT) || + (thd->options & OPTION_BEGIN)) + { + if (ha_commit(thd)) + return 1; + thd->options&= ~OPTION_BEGIN; + thd->server_status&= ~SERVER_STATUS_IN_TRANS; + } + return 0; +} + + /* ** Check if user is ok ** Updates: @@ -1150,8 +1164,7 @@ mysql_execute_command(void) } } /* ALTER TABLE ends previous transaction */ - if ((!(thd->options & OPTION_AUTO_COMMIT) || - (thd->options & OPTION_BEGIN)) && ha_commit(thd)) + if (end_active_trans(thd)) res= -1; else res= mysql_alter_table(thd, lex->db, lex->name, @@ -1369,6 +1382,7 @@ mysql_execute_command(void) break; } case SQLCOM_DELETE: + case SQLCOM_TRUNCATE: { if (check_access(thd,DELETE_ACL,tables->db,&tables->grant.privilege)) goto error; /* purecov: inspected */ @@ -1376,11 +1390,12 @@ mysql_execute_command(void) goto error; // Set privilege for the WHERE clause tables->grant.want_privilege=(SELECT_ACL & ~tables->grant.privilege); - res = mysql_delete(thd,tables,lex->where,lex->select_limit, - lex->lock_option, lex->options); -#ifdef DELETE_ITEMS - delete lex->where; -#endif + /* TRUNCATE ends previous transaction */ + if (lex->sql_command == SQLCOM_TRUNCATE && end_active_trans(thd)) + res= -1; + else + res = mysql_delete(thd,tables,lex->where,lex->select_limit, + lex->lock_option, lex->options); break; } case SQLCOM_DROP_TABLE: @@ -1722,6 +1737,11 @@ mysql_execute_command(void) send_ok(&thd->net); break; case SQLCOM_COMMIT: + /* + We don't use end_active_trans() here to ensure that this works + even if there is a problem with the OPTION_AUTO_COMMIT flag + (Which of course should never happen...) + */ thd->options&= ~OPTION_BEGIN; thd->server_status&= ~SERVER_STATUS_IN_TRANS; if (!ha_commit(thd)) @@ -2441,7 +2461,7 @@ bool reload_acl_and_cache(THD *thd, uint options, TABLE_LIST *tables) bool result=0; select_errors=0; /* Write if more errors */ - mysql_log.flush(); // Flush log + // mysql_log.flush(); // Flush log if (options & REFRESH_GRANT) { acl_reload(); diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 4142c003d4d..5cdb5ab0706 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -93,6 +93,40 @@ static int send_file(THD *thd) DBUG_RETURN(error); } + +static File open_log(IO_CACHE *log, const char *log_file_name, + const char **errmsg) +{ + File file; + char magic[4]; + if ((file = my_open(log_file_name, O_RDONLY | O_BINARY, MYF(MY_WME))) < 0 || + init_io_cache(log, file, IO_SIZE*2, READ_CACHE, 0, 0, + MYF(MY_WME))) + { + *errmsg = "Could not open log file"; // This will not be sent + goto err; + } + + if (my_b_read(log, (byte*) magic, sizeof(magic))) + { + *errmsg = "I/O error reading binlog magic number"; + goto err; + } + if (memcmp(magic, BINLOG_MAGIC, 4)) + { + *errmsg = "Binlog has bad magic number, fire your magician"; + goto err; + } + return file; + +err: + if (file > 0) + my_close(file,MYF(0)); + end_io_cache(log); + return -1; +} + + void adjust_linfo_offsets(my_off_t purge_offset) { THD *tmp; @@ -119,6 +153,7 @@ void adjust_linfo_offsets(my_off_t purge_offset) pthread_mutex_unlock(&LOCK_thread_count); } + bool log_in_use(const char* log_name) { int log_name_len = strlen(log_name) + 1; @@ -144,6 +179,7 @@ bool log_in_use(const char* log_name) return result; } + int purge_master_logs(THD* thd, const char* to_log) { char search_file_name[FN_REFLEN]; @@ -179,27 +215,29 @@ binlog purge"; break; return 0; } + void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags) { LOG_INFO linfo; char *log_file_name = linfo.log_file_name; char search_file_name[FN_REFLEN]; - char magic[4]; - FILE* log = NULL; + IO_CACHE log; + File file = -1; String* packet = &thd->packet; int error; const char *errmsg = "Unknown error"; NET* net = &thd->net; - DBUG_ENTER("mysql_binlog_send"); + bzero((char*) &log,sizeof(log)); + if(!mysql_bin_log.is_open()) - { - errmsg = "Binary log is not open"; - goto err; - } + { + errmsg = "Binary log is not open"; + goto err; + } - if(log_ident[0]) + if (log_ident[0]) mysql_bin_log.make_log_name(search_file_name, log_ident); else search_file_name[0] = 0; @@ -207,251 +245,214 @@ void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags) linfo.index_file_offset = 0; thd->current_linfo = &linfo; - if(mysql_bin_log.find_first_log(&linfo, search_file_name)) - { - errmsg = "Could not find first log"; - goto err; - } - log = my_fopen(log_file_name, O_RDONLY|O_BINARY, MYF(MY_WME)); + if (mysql_bin_log.find_first_log(&linfo, search_file_name)) + { + errmsg = "Could not find first log"; + goto err; + } - if(!log) - { - errmsg = "Could not open log file"; - goto err; - } - - if(my_fread(log, (byte*) magic, sizeof(magic), MYF(MY_NABP|MY_WME))) - { - errmsg = "I/O error reading binlog magic number"; - goto err; - } - if(memcmp(magic, BINLOG_MAGIC, 4)) - { - errmsg = "Binlog has bad magic number, fire your magician"; - goto err; - } + if ((file=open_log(&log, log_file_name, &errmsg)) < 0) + goto err; if(pos < 4) - { - errmsg = "Congratulations! You have hit the magic number and can win \ + { + errmsg = "Contratulations! You have hit the magic number and can win \ sweepstakes if you report the bug"; - goto err; - } - - if(my_fseek(log, pos, MY_SEEK_SET, MYF(MY_WME)) == MY_FILEPOS_ERROR ) - { - errmsg = "Error on fseek()"; - goto err; - } - - + goto err; + } + + my_b_seek(&log, pos); // Seek will done on next read packet->length(0); packet->append("\0", 1); // we need to start a packet with something other than 255 // to distiquish it from error while(!net->error && net->vio != 0 && !thd->killed) - { - pthread_mutex_t *log_lock = mysql_bin_log.get_log_lock(); + { + pthread_mutex_t *log_lock = mysql_bin_log.get_log_lock(); - while(!(error = Log_event::read_log_event(log, packet, log_lock))) - { - if(my_net_write(net, (char*)packet->ptr(), packet->length()) ) - { - errmsg = "Failed on my_net_write()"; - goto err; - } - DBUG_PRINT("info", ("log event code %d", - (*packet)[LOG_EVENT_OFFSET+1] )); - if((*packet)[LOG_EVENT_OFFSET+1] == LOAD_EVENT) - { - if(send_file(thd)) - { - errmsg = "failed in send_file()"; - goto err; - } - } - packet->length(0); - packet->append("\0",1); - } - if(error != LOG_READ_EOF) + while (!(error = Log_event::read_log_event(&log, packet, log_lock))) + { + if(my_net_write(net, (char*)packet->ptr(), packet->length()) ) + { + errmsg = "Failed on my_net_write()"; + goto err; + } + DBUG_PRINT("info", ("log event code %d", + (*packet)[LOG_EVENT_OFFSET+1] )); + if((*packet)[LOG_EVENT_OFFSET+1] == LOAD_EVENT) + { + if(send_file(thd)) { - switch(error) - { - case LOG_READ_BOGUS: - errmsg = "bogus data in log event"; - break; - case LOG_READ_IO: - errmsg = "I/O error reading log event"; - break; - case LOG_READ_MEM: - errmsg = "memory allocation failed reading log event"; - break; - case LOG_READ_TRUNC: - errmsg = "binlog truncated in the middle of event"; - break; - } + errmsg = "failed in send_file()"; goto err; } + } + packet->length(0); + packet->append("\0",1); + } + if(error != LOG_READ_EOF) + { + switch(error) + { + case LOG_READ_BOGUS: + errmsg = "bogus data in log event"; + break; + case LOG_READ_IO: + errmsg = "I/O error reading log event"; + break; + case LOG_READ_MEM: + errmsg = "memory allocation failed reading log event"; + break; + case LOG_READ_TRUNC: + errmsg = "binlog truncated in the middle of event"; + break; + } + goto err; + } - if(!(flags & BINLOG_DUMP_NON_BLOCK) && - mysql_bin_log.is_active(log_file_name)) - // block until there is more data in the log - // unless non-blocking mode requested - { - if(net_flush(net)) - { - errmsg = "failed on net_flush()"; - goto err; - } + if(!(flags & BINLOG_DUMP_NON_BLOCK) && + mysql_bin_log.is_active(log_file_name)) + // block until there is more data in the log + // unless non-blocking mode requested + { + if(net_flush(net)) + { + errmsg = "failed on net_flush()"; + goto err; + } - // we may have missed the update broadcast from the log - // that has just happened, let's try to catch it if it did - // if we did not miss anything, we just wait for other threads - // to signal us - { - clearerr(log); - - // tell the kill thread how to wake us up - pthread_mutex_lock(&thd->mysys_var->mutex); - thd->mysys_var->current_mutex = log_lock; - thd->mysys_var->current_cond = &COND_binlog_update; - const char* proc_info = thd->proc_info; - thd->proc_info = "Waiting for update"; - pthread_mutex_unlock(&thd->mysys_var->mutex); - - bool read_packet = 0, fatal_error = 0; - - // no one will update the log while we are reading - // now, but we'll be quick and just read one record - switch(Log_event::read_log_event(log, packet, log_lock)) - { - case 0: - read_packet = 1; - // we read successfully, so we'll need to send it to the - // slave - break; - case LOG_READ_EOF: - pthread_mutex_lock(log_lock); - pthread_cond_wait(&COND_binlog_update, log_lock); - pthread_mutex_unlock(log_lock); - break; - - default: - fatal_error = 1; - break; - } - - - pthread_mutex_lock(&thd->mysys_var->mutex); - thd->mysys_var->current_mutex= 0; - thd->mysys_var->current_cond= 0; - thd->proc_info= proc_info; - pthread_mutex_unlock(&thd->mysys_var->mutex); - - if(read_packet) - { - thd->proc_info = "sending update to slave"; - if(my_net_write(net, (char*)packet->ptr(), packet->length()) ) - { - errmsg = "Failed on my_net_write()"; - goto err; - } - - if((*packet)[LOG_EVENT_OFFSET+1] == LOAD_EVENT) - { - if(send_file(thd)) - { - errmsg = "failed in send_file()"; - goto err; - } - } - packet->length(0); - packet->append("\0",1); - // no need to net_flush because we will get to flush later when - // we hit EOF pretty quick - } + // we may have missed the update broadcast from the log + // that has just happened, let's try to catch it if it did + // if we did not miss anything, we just wait for other threads + // to signal us + { + log.error=0; - if(fatal_error) - { - errmsg = "error reading log entry"; - goto err; - } + // tell the kill thread how to wake us up + pthread_mutex_lock(&thd->mysys_var->mutex); + thd->mysys_var->current_mutex = log_lock; + thd->mysys_var->current_cond = &COND_binlog_update; + const char* proc_info = thd->proc_info; + thd->proc_info = "Waiting for update"; + pthread_mutex_unlock(&thd->mysys_var->mutex); - clearerr(log); - } - } - else + bool read_packet = 0, fatal_error = 0; + + // no one will update the log while we are reading + // now, but we'll be quick and just read one record + switch(Log_event::read_log_event(&log, packet, log_lock)) { - bool loop_breaker = 0; - // need this to break out of the for loop from switch - thd->proc_info = "switching to next log"; - switch(mysql_bin_log.find_next_log(&linfo)) - { - case LOG_INFO_EOF: - loop_breaker = (flags & BINLOG_DUMP_NON_BLOCK); - break; - case 0: - break; - default: - errmsg = "could not find next log"; - goto err; - } + case 0: + read_packet = 1; + // we read successfully, so we'll need to send it to the + // slave + break; + case LOG_READ_EOF: + pthread_mutex_lock(log_lock); + pthread_cond_wait(&COND_binlog_update, log_lock); + pthread_mutex_unlock(log_lock); + break; + + default: + fatal_error = 1; + break; + } - if(loop_breaker) - break; + pthread_mutex_lock(&thd->mysys_var->mutex); + thd->mysys_var->current_mutex= 0; + thd->mysys_var->current_cond= 0; + thd->proc_info= proc_info; + pthread_mutex_unlock(&thd->mysys_var->mutex); - (void) my_fclose(log, MYF(MY_WME)); - log = my_fopen(log_file_name, O_RDONLY|O_BINARY, MYF(MY_WME)); - if(!log) - { - errmsg = "Could not open next log"; - goto err; - } + if(read_packet) + { + thd->proc_info = "sending update to slave"; + if(my_net_write(net, (char*)packet->ptr(), packet->length()) ) + { + errmsg = "Failed on my_net_write()"; + goto err; + } - //check the magic - if(my_fread(log, (byte*) magic, sizeof(magic), MYF(MY_NABP|MY_WME))) - { - errmsg = "I/O error reading binlog magic number"; - goto err; - } - if(memcmp(magic, BINLOG_MAGIC, 4)) + if((*packet)[LOG_EVENT_OFFSET+1] == LOAD_EVENT) + { + if(send_file(thd)) { - errmsg = "Binlog has bad magic number, fire your magician"; + errmsg = "failed in send_file()"; goto err; } - - // fake Rotate_log event just in case it did not make it to the log - // otherwise the slave make get confused about the offset - { - char header[LOG_EVENT_HEADER_LEN]; - memset(header, 0, 4); // when does not matter - header[EVENT_TYPE_OFFSET] = ROTATE_EVENT; - char* p = strrchr(log_file_name, FN_LIBCHAR); - // find the last slash - if(p) - p++; - else - p = log_file_name; - - uint ident_len = (uint) strlen(p); - ulong event_len = ident_len + sizeof(header); - int4store(header + EVENT_TYPE_OFFSET + 1, server_id); - int4store(header + EVENT_LEN_OFFSET, event_len); - packet->append(header, sizeof(header)); - packet->append(p,ident_len); - if(my_net_write(net, (char*)packet->ptr(), packet->length())) - { - errmsg = "failed on my_net_write()"; - goto err; - } - packet->length(0); - packet->append("\0",1); } + packet->length(0); + packet->append("\0",1); + // no need to net_flush because we will get to flush later when + // we hit EOF pretty quick + } + + if(fatal_error) + { + errmsg = "error reading log entry"; + goto err; } + log.error=0; + } } + else + { + bool loop_breaker = 0; + // need this to break out of the for loop from switch + thd->proc_info = "switching to next log"; + switch(mysql_bin_log.find_next_log(&linfo)) + { + case LOG_INFO_EOF: + loop_breaker = (flags & BINLOG_DUMP_NON_BLOCK); + break; + case 0: + break; + default: + errmsg = "could not find next log"; + goto err; + } + + if(loop_breaker) + break; + + end_io_cache(&log); + (void) my_close(file, MYF(MY_WME)); + if ((file=open_log(&log, log_file_name, &errmsg)) < 0) + goto err; + + // fake Rotate_log event just in case it did not make it to the log + // otherwise the slave make get confused about the offset + { + char header[LOG_EVENT_HEADER_LEN]; + memset(header, 0, 4); // when does not matter + header[EVENT_TYPE_OFFSET] = ROTATE_EVENT; + char* p = strrchr(log_file_name, FN_LIBCHAR); + // find the last slash + if(p) + p++; + else + p = log_file_name; + + uint ident_len = (uint) strlen(p); + ulong event_len = ident_len + sizeof(header); + int4store(header + EVENT_TYPE_OFFSET + 1, server_id); + int4store(header + EVENT_LEN_OFFSET, event_len); + packet->append(header, sizeof(header)); + packet->append(p,ident_len); + if(my_net_write(net, (char*)packet->ptr(), packet->length())) + { + errmsg = "failed on my_net_write()"; + goto err; + } + packet->length(0); + packet->append("\0",1); + } + } + } - (void)my_fclose(log, MYF(MY_WME)); + end_io_cache(&log); + (void)my_close(file, MYF(MY_WME)); send_eof(&thd->net); thd->proc_info = "waiting to finalize termination"; @@ -461,6 +462,7 @@ sweepstakes if you report the bug"; DBUG_VOID_RETURN; err: thd->proc_info = "waiting to finalize termination"; + end_io_cache(&log); pthread_mutex_lock(&LOCK_thread_count); // exclude iteration through thread list // this is needed for purge_logs() - it will iterate through @@ -469,8 +471,8 @@ sweepstakes if you report the bug"; // after we return from this stack frame thd->current_linfo = 0; pthread_mutex_unlock(&LOCK_thread_count); - if(log) - (void) my_fclose(log, MYF(MY_WME)); + if (file >= 0) + (void) my_close(file, MYF(MY_WME)); send_error(&thd->net, my_errno, errmsg); DBUG_VOID_RETURN; } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index c9de4998899..f38b1a52b65 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -2735,7 +2735,7 @@ return_zero_rows(select_result *result,TABLE_LIST *tables,List<Item> &fields, { for (TABLE_LIST *table=tables; table ; table=table->next) mark_as_null_row(table->table); // All fields are NULL - if (having && having->val_int() == 0.0) + if (having && having->val_int() == 0) send_row=0; } if (!tables || !(result->send_fields(fields,1))) @@ -3214,6 +3214,7 @@ Field *create_tmp_field(TABLE *table,Item *item, Item::Type type, case Item::REAL_ITEM: case Item::STRING_ITEM: case Item::REF_ITEM: + case Item::NULL_ITEM: { bool maybe_null=item->maybe_null; Field *new_field; @@ -4499,7 +4500,7 @@ end_send(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), if (!end_of_records) { int error; - if (join->having && join->having->val_int() == 0.0) + if (join->having && join->having->val_int() == 0) DBUG_RETURN(0); // Didn't match having if (join->procedure) error=join->procedure->send_row(*join->fields); @@ -4539,7 +4540,7 @@ end_send_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), int error; if (join->procedure) { - if (join->having && join->having->val_int() == 0.0) + if (join->having && join->having->val_int() == 0) error= -1; // Didn't satisfy having else error=join->procedure->send_row(*join->fields) ? 1 : 0; @@ -4550,7 +4551,7 @@ end_send_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), { if (!join->first_record) clear_tables(join); - if (join->having && join->having->val_int() == 0.0) + if (join->having && join->having->val_int() == 0) error= -1; // Didn't satisfy having else error=join->result->send_data(*join->fields) ? 1 : 0; @@ -5109,7 +5110,7 @@ create_sort_index(JOIN_TAB *tab,ORDER *order,ha_rows select_limit) goto err; /* purecov: inspected */ /* It's not fatal if the following alloc fails */ table->io_cache=(IO_CACHE*) my_malloc(sizeof(IO_CACHE), - MYF(MY_FAE | MY_ZEROFILL)); + MYF(MY_WME | MY_ZEROFILL)); table->status=0; // May be wrong if quick_select // If table has a range, move it to select diff --git a/sql/sql_string.cc b/sql/sql_string.cc index 7ca2d3c419e..4b9ebef21f1 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -95,17 +95,6 @@ bool String::realloc(uint32 alloc_length) return FALSE; } - -#ifdef NOT_NEEDED -bool String::set(long num) -{ - if (alloc(14)) - return TRUE; - str_length=(uint32) (int10_to_str(num,Ptr,-10)-Ptr); - return FALSE; -} -#endif - bool String::set(longlong num) { if (alloc(21)) @@ -274,6 +263,7 @@ bool String::append(const char *s,uint32 arg_length) return FALSE; } +#ifdef TO_BE_REMOVED bool String::append(FILE* file, uint32 arg_length, myf my_flags) { if (realloc(str_length+arg_length)) @@ -286,6 +276,20 @@ bool String::append(FILE* file, uint32 arg_length, myf my_flags) str_length+=arg_length; return FALSE; } +#endif + +bool String::append(IO_CACHE* file, uint32 arg_length) +{ + if (realloc(str_length+arg_length)) + return TRUE; + if (my_b_read(file, (byte*) Ptr + str_length, arg_length)) + { + shrink(str_length); + return TRUE; + } + str_length+=arg_length; + return FALSE; +} uint32 String::numchars() { diff --git a/sql/sql_string.h b/sql/sql_string.h index 1c9e822cce5..f327618ffdd 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -152,7 +152,7 @@ public: bool copy(const char *s,uint32 arg_length); // Allocate new string bool append(const String &s); bool append(const char *s,uint32 arg_length=0); - bool append(FILE* file, uint32 arg_length, myf my_flags); + bool append(IO_CACHE* file, uint32 arg_length); int strstr(const String &search,uint32 offset=0); // Returns offset to substring or -1 int strrstr(const String &search,uint32 offset=0); // Returns offset to substring or -1 bool replace(uint32 offset,uint32 arg_length,const String &to); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 5d62fbe84ba..4923be08a49 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -111,6 +111,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token SLAVE %token START_SYM %token STOP_SYM +%token TRUNCATE_SYM %token ROLLBACK_SYM %token OPTIMIZE %token SHOW @@ -493,9 +494,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %type <NONE> query verb_clause create change select drop insert replace insert2 - insert_values update delete show describe load alter optimize flush + insert_values update delete truncate rename + show describe load alter optimize flush reset purge begin commit rollback slave master_def master_defs - repair restore backup analyze check rename + repair restore backup analyze check field_list field_list_item field_spec kill select_item_list select_item values_list no_braces limit_clause delete_limit_clause fields opt_values values @@ -562,6 +564,7 @@ verb_clause: | set | slave | show + | truncate | unlock | update | use @@ -789,7 +792,7 @@ field_list_item: Lex->key_list.push_back(new Key($1,$2,Lex->col_list)); Lex->col_list.empty(); /* Alloced by sql_alloc */ } - | opt_constraint FOREIGN KEY_SYM '(' key_list ')' references + | opt_constraint FOREIGN KEY_SYM opt_ident '(' key_list ')' references { Lex->col_list.empty(); /* Alloced by sql_alloc */ } @@ -1559,7 +1562,8 @@ simple_expr: { $$= new Item_func_trim($6,$4); } | TRIM '(' expr FROM expr ')' { $$= new Item_func_trim($5,$3); } - + | TRUNCATE_SYM '(' expr ',' expr ')' + { $$= new Item_func_round($3,$5,1); } | UDA_CHAR_SUM '(' udf_expr_list ')' { if ($3 != NULL) @@ -2131,6 +2135,11 @@ opt_delete_option: QUICK { Lex->options|= OPTION_QUICK; } | LOW_PRIORITY { Lex->lock_option= TL_WRITE_LOW_PRIORITY; } +truncate: + TRUNCATE_SYM TABLE_SYM table + { Lex->sql_command= SQLCOM_TRUNCATE; Lex->options=0; + Lex->lock_option= current_thd->update_lock_default; } + /* Show things */ show: SHOW { Lex->wild=0;} show_param @@ -2530,6 +2539,7 @@ keyword: | STRING_SYM {} | TEMPORARY {} | TEXT_SYM {} + | TRUNCATE_SYM {} | TIMESTAMP {} | TIME_SYM {} | TYPE_SYM {} diff --git a/sql/time.cc b/sql/time.cc index 17603d93dd4..ce4b5b0e30c 100644 --- a/sql/time.cc +++ b/sql/time.cc @@ -413,16 +413,6 @@ ulong convert_month_to_period(ulong month) return year*100+month%12+1; } -#ifdef NOT_NEEDED - -ulong add_to_period(ulong period,int months) -{ - if (period == 0L) - return 0L; - return convert_month_to_period(convert_period_to_month(period)+months); -} -#endif - /***************************************************************************** ** convert a timestamp string to a TIME value. diff --git a/sql/violite.c b/sql/violite.c index b18de053b5a..4efda9f3b90 100644 --- a/sql/violite.c +++ b/sql/violite.c @@ -1,18 +1,19 @@ /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB - 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 - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, + This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ /* Note that we can't have assertion on file descriptors; The reason for @@ -31,6 +32,9 @@ #include <my_sys.h> #include <my_net.h> #include <m_string.h> +#ifdef HAVE_POLL +#include <sys/poll.h> +#endif #if defined(__EMX__) #include <sys/ioctl.h> @@ -398,4 +402,26 @@ void vio_in_addr(Vio *vio, struct in_addr *in) DBUG_VOID_RETURN; } + +/* Return 0 if there is data to be read */ + +my_bool vio_poll_read(Vio *vio,uint timeout) +{ +#ifndef HAVE_POLL + return 0; +#else + struct pollfd fds; + int res; + DBUG_ENTER("vio_poll"); + fds.fd=vio->sd; + fds.events=POLLIN; + fds.revents=0; + if ((res=poll(&fds,1,(int) timeout*1000)) <= 0) + { + DBUG_RETURN(res < 0 ? 0 : 1); /* Don't return 1 on errors */ + } + DBUG_RETURN(fds.revents & POLLIN ? 0 : 1); +#endif +} + #endif /* HAVE_VIO */ diff --git a/strings/strstr-sparc.s b/strings/strstr-sparc.s index 141c3aa4209..1263236f107 100644 --- a/strings/strstr-sparc.s +++ b/strings/strstr-sparc.s @@ -31,7 +31,7 @@ strstr: ! if (*str++ == *search) { ! i=(char*) str; j=(char*) search+1; - ldsb [%o1],%o2 ! g6= First char of search + ldsb [%o1],%o2 ! o2= First char of search .top: ldsb [%o0],%g3 ! g3= First char of rest of str cmp %g3,0 @@ -70,6 +70,3 @@ strstr: .strstr_end: .size strstr,.strstr_end-strstr .ident "Matt Wagner & Monty" - - - |