START-INFO-DIR-ENTRY
* mysql: (mysql).               *MySQL* documenatation.
END-INFO-DIR-ENTRY

This is a manual for *MySQL*. This
version is about the 3.21.18a-beta version of *MySQL*. For a *3.20*
version see the relevant distribution.

General Information about *MySQL*
*********************************

   This is the *MySQL* reference manual. This version documents the
3.21.18a-beta version of *MySQL*.

   *MySQL* is a basically free SQL database server. *Note Licensing and
Support::.

   The latest information about *MySQL* is found at the *MySQL* Home page (http://www.tcx.se)

   To see what it can do. *Note Features::.

   For installation instructions *Note Installing::. For tips on how to
port *MySQL* to new machines/operating systems *Note Porting::.

   If you have any suggestions concerning additions or corrections to
this manual, please send them to the *MySQL* mailing list
<mysql@tcx.se> with a subject line like: `doc: [Insert Topic Here]'.
*Note Mailing-list::.

   *Note Upgrading-from-3.20::, for information about upgrading from a
3.20 release.

   For examples of SQL and benchmarking information see the `bench'
directory.

   For future plans *Note Todo::.

   A history of new features/bug fixes *Note News::.

   For the currently known bugs/misfeatures (known errors) *Note Bugs::.

   For A list of all the contributors to this product *Note Credits::.

   *IMPORTANT:*

   Send bug (error) reports, questions and comments to the mailing list
at <mysql@tcx.se>

   Please use the `mysqlbug' script when posting bug reports or
questions about *MySQL*. `mysqlbug' will gather some information about
your system and start your editor with a form in which you can describe
your problem. Bug reports might be silently ignored by the *MySQL*
maintainers if there is not a good reason included in the report as to
why mysqlbug has not been used. A report that says 'MySQL does not work
for me. Why?'  is not consider a valid bug report.

   The mysqlbug script can be found in the `scripts' directory in the
distribution, that is `there-you-installed-mysql/scripts'.

About this manual
=================

   This manual is currently available in TeXInfo, Raw text, Info,
PostScript and HTML versions.

   The primary document is the TeXInfo file. The HTML version is
automatically produced with a modified `texi2html'. The ASCII and info
version are produced with `makeinfo'. The Postscript version is
produced using `texi2dvi' and `dvips'.

   This manual was written and is maintained by David Axmark, Michael
(Monty) Widenius and Kim Aldale. The DBI chapter was original written by
Jay Flaherty.

What is *MySQL*?
================

   *MySQL* is a SQL (Structured Query Language) database server.  SQL
is the most popular database language in the world. *MySQL* is a client
server implementation that consists of a server daemon `mysqld' and
many different client programs/libraries.

   The main goals of *MySQL* are speed and robustness.

   The base upon which *MySQL* is built is a set of routines that have
been used in a highly demanding production environment for many years.
While *MySQL* is still in development it already offers a rich and
highly useful function set.

   The official way to pronounce *MySQL* is 'My Ess Que Ell' (Not
MY-SEQUAL).

History of *MySQL*
==================

   We once started off with the intention to use `mSQL' to connect to
our own fast low level (ISAM) tables. However, after some testing we
came to the conclusion that `mSQL' was not fast or flexible enough for
our needs. This resulted in a new SQL interface to our database but
with almost the same API interface as `mSQL'. This API was chosen to
ease porting of third party code.

   It is not perfectly clear where the name *MySQL* derives from. Our
base directory and a large amount of our libraries and tools have had
the prefix 'my' for well over 10 years. However, Monty's daughter (some
years younger) is also named My. So which of the two gave its name to
*MySQL* is still a mystery, even for us.

The main features of *MySQL*
============================

   * Fully multi-threaded using kernel threads. That means that it
     easily can use multiple CPUs if availably.

   * C, C++, JAVA, Perl, Python and TCL API's. *Note Clients::

   * Lots of column types like: signed/unsigned integers 1,2,3,4 and 8
     bytes long, `FLOAT', `DOUBLE', `CHAR', `VARCHAR', `TEXT', `BLOB',
     `DATE', `SET' and `ENUM' types. *Note Column types::

   * Very fast joins using a optimized one-sweep multi-join.

   * Full function support in the SELECT and WHERE parts. Example:
     `select column1 + column2 from table where column1/column2 > 0'

   * SQL functions are implemented through a very optimised class
     library and should be as fast as they can get! Usually there
     shouldn't be any memory allocation at all after the query
     initialisation.

   * Full support for SQL `GROUP BY' and `ORDER BY'. Support for group
     functions (`COUNT', `AVG', `SUM', `MAX' and `MIN').

   * Support for `LEFT OUTER JOIN' with ANSI SQL and ODBC syntax.

   * A privilege and password system with is very flexible and secure.
     Allows host based verification.

   * Secure passwords since all password traffic on the net is
     encrypted.

   * ODBC Open-DataBase-Connectivity for Windows95 (with source). All
     ODBC 2.5 functions and lots of others. So you can for exapmple use
     Access to connect to your *MySQL* server. *Note ODBC::

   * Very fast B-tree disk tables with index compression.

   * 16 indexes/table. Each index may consist of 1 to 15 columns/parts
     of columns. Max index length is 127 bytes. A index may be a prefix
     of a CHAR field.

   * Fixed and variable length records.

   * In memory hash tables always used as temporary tables.

   * Can handle big databases (we are using *MySQL* with some databases
     that contain 50,000,000 records).

   * All columns have default values. One can always use INSERT on any
     subset of columns.

   * Uses GNU autoconf for portability.

   * Written in C and C++. Tested with gcc 2.7.2.

   * A very fast thread based memory allocation system.

   * No memory leaks. Tested with a commercial memory leakage detector
     (purify).

   * A very fast table check,optimize and repair utility. *Note
     isamchk::

   * All data saved in ISO8859_1 format. All comparisons for normal
     string columns are case insensitive.

   * Full ISO8859_1 (Latin1) support. For example Scandinavian едц is
     allowed in table and column names.

   * Sorts by ISO8859_1 Latin1 (the Swedish way at the moment). It is
     possible to change this in the source by adding new sort order
     arrays. To see a example of a very advanced sorting look at the
     Czeck sorting code.

   * Alias on tables and columns as in the SQL92 standard.

   * `DELETE', `INSERT', `REPLACE', and `UPDATE' returns how many rows
     were affected.

   * Function names do not clash with table or column names. For
     example ABS is a valid column name. *Note Reserved words::

   * All *MySQL* commands have `--help' or `-?' for help.

   * The server currently supports error messages to clients in many
     languages. *Note Languages::.

   * The clients uses a TCP connection or unix socket when connecting
     to the *MySQL* server.

   * User commands as `show tables', `show index from table' and `show
     columns from table'

General SQL information and tutorials
=====================================

   There is one SQL tutor (http://w3.one.net/~jhoffman/sqltut.htm) on
the net.

   This book has been recommended by a lot of people on the *MySQL*
mailing list.

     Judith S. Bowman, Sandra L. Emerson and Marcy Darnovsky
     "The Practical SQL Handbook: Using Structured Query Language"
     Second Edition
     Addison Wesley
     ISBN 0-201-62623-3
     http://www.awl.com

   And another book also recommended by people on the *MySQL* mailing
list.

     Understanding SQL
     ISBN 0-89588-644-8
     Publisher Sybex 510 523 8233
     Alameda CA USA

Usefull MySQL related links
===========================

Some web development tools what supports *MySQL*
------------------------------------------------

   * PHP A server-side HTML-embedded scripting      language (http://php.iquest.net)

   * *MySQL* + PHP demos (http://www.wernhart.priv.at/php/)

   * WWW-SQL display databases      information (http://www.daa.com.au/~james/www-sql/)

   * Web shopping cart (http://www.minivend.com/minivend/)

   * Metahtml A Dynamic Programming Language      for WWW Applications (http://www.metahtml.com)

Web servers with *MySQL* tools
------------------------------

   * A Apache      authentication module (http://bourbon.netvision.net.il/mysql/mod_auth_mysql/)

   * The Roxen Challenger Web server (http://www.roxen.com)

Other *MySQL* related links.
----------------------------

   * Comercial Web defect      tracking system (http://www.open.com.au/products.html)

   * PTS - Project Tracking      System (http://www.homeport.org/~shevett/pts/)

   * Support for BIND (The Internet      Domain Name Server) (http://www.seawood.org/msql_bind/)

   * A REXX interface      to SQL databases (http://www.lightlink.com/hessling/rexxsql.html)

   * Registry over Web providers who      supports *MySQL* (http://www.wix.com/mysql-hosting)

   * *MySQL* TCL patch homepage (http://www.gagme.com/mysql)

   * Full text search engine for      *MySQL* (http://www.pi.net/~hverbeek/mysql/)

   * WDB; Web browser as      a universal front end to databases (http://www.lava.net/beowulf/programming/wdb/)

   * EasySQL; An ODBC like driver manager
     (http://www.amsoft.ru/easysql/)

   * Network Database Connection For Linux (http://www.fastflow.com/)

   * ExportSQL A script      to export data from Access (http://www.cynergi.net/non-secure/exportsql/)

   * SAL (Scientific      Applications on Linux) *MySQL* entry (http://SAL.KachinaTech.COM/H/1/MYSQL.html)

   * *MySQL* Apps and Utilities      Listing (http://www.cgishop.com/bin/mysqllist)

   * The *MySQL*      reference manual in Adobe PDF format (http://www.luth.se/~goggi/proj/mysql/man/mysql.pdf)

   * A consulting company      who mentions *MySQL* in the right company. (http://www.infotech-nj.com/itech/index.shtml)

General database links.
-----------------------

   * Database Jump Site (http://www.pcslink.com/~ej/dbweb.html)

   * The JDBC database access API (http://java.sun.com/products/jdbc/)

   * Homepage of the webdb-l      (Web Databases) mailing list. (http://black.hole-in-the.net/guy/webdb/)

   There are also a lot of web pages that uses *MySQL*. *Note Users::.

What are stored procedures and triggers and so on?
==================================================

   A stored procedure is some code that is stored and run in the
server. After this the client doesn't have to issue the whole query but
can refer to the stored procedure. This gives more speed because the
query only has to be parsed once and less data has to be sent between
the server and the client. You can also raise the conceptual level by
having libraries of functions in the server.

   A trigger is a stored procedure that is invoked when something
happens.  For example one can install a stored procedure that checks
every delete to a transaction table and does a automatic delete on the
corresponding customer when all his transactions are deleted.

   To se when *MySQL* migth get theese function set the todo. *Note
Todo::.

*MySQL* mailing lists and how to ask questions/give error (bug) reports
***********************************************************************

Subscribing to/un-subscribing from the *MySQL* mailing list.
============================================================

   Requests to be added or dropped from the *MySQL* list should be sent
to the electronic mail address <mdomo@tcx.se>. Sending a one line
message saying either `subscribe mysql' or `unsubscribe mysql' will
suffice. If your reply address is not valid you may use `subscribe
mysql your@address.your-domain' or `unsubscribe mysql
your@address.your-domain'.

   Please *do not* send mail about [un]subscribing to <mysql@tcx.se>
since any mail sent to this address is automatically forwarded to
hundreds of other users.

   Your local site may have many subscribers to *MySQL*. In that case,
it may have a local mailing list, so that a single message from
`tcx.se' is sent to the site and propagated to the local list. In such
cases, please contact your system administrator to be added to or
dropped from the local *MySQL* list.

   Mail to `mdomo' is handled automatically by majordomo.

Asking questions or reporting bugs.
===================================

   Before you ask a question on the mailing list it is a good idea to
check this manual. If you can't find an answer here, check with your
local *MySQL* expert. If you still can't find an answer to your
question go ahead and read the next section about how to send mail to
<mysql@tcx.se>.

I think I have found a bug. What information do you need to help me?
====================================================================

   If you can, please use the `mysqlbug' script that can be found in
the scripts directory in the distribution. If that is not possible,
remember to specify (if relevant) the following. Note that it is
possible to answer a letter with to much information but not one with to
little.

  1. State which version of *MySQL* you are using (for example
     mysql-3.21..tgz). You can find out which version you are running by
     typing `mysqladmin version'.

  2. The manufacturer and model of machine you are working on.

  3. The operating system. For most operating systems you can get this
     from `uname -a'.

  4. Sometimes the amount of memory (real and virtual) is also relevant.

  5. If this is a bug when compiling: Include the exact error messages
     and also a few lines around the offending code in the file from
     which you got the error.

  6. If this is a run time bug, please describe exactly how you got the
     error. If you can include a test program which shows the error you
     can get a more explicit answer.

   If you are a support customer, please post the bug report to the
specified mailing list for higher priority treatment.

   When answers are sent to you individually and not to the mailing
list, it is considered good etiquette to summarise the answers and mail
them to the mailing list.

*MySQL* keeps crashing
----------------------

   Since it is very hard to now why something crashing please do one of
the following things.

   First try to check if thigs that work for other crash for you:

   * Have you tried the benchmarks?  This should test MySQL rather
     well. You can also add code that simulates your application!

   * Try also fork_test.pl and fork2_test.pl

   * Check the reference manual about debugging mysqld.

   * Recompile *MySQL* with `--with-debug' switch to configure. This
     will include a safe memory allocator that can find some errors.
     This also gives a lot of output about what is happening.

   * Use mysqld -log and try to find if it some specific query that
     kills it. 95% of all bugs is related to some specific query!

   * Have you applied the latest patches for your Operatying System ?

   * Use -skip-locking

   * Have you tried 'mysqladmin proc' when it 'dies' ?

   * Put in some window the following command to output statistics:
     mysqladmin -i 5 status

   *       1. Start mysqld with gdb (or another debugger).

       2. Run your test scripts.

       3. Do `back' (or the backtrace command in your debugger) when
          `mysqld' core dumps.

   * Try to simulate your application with a perl script to force
     *MySQL* to crash/misbehave.

   * Or send a normal bug report. *Note Bug reports::. But be even more
     detailed than normally. Since *MySQL* works for a lot of people it
     may that the crash comes from something that only exists on your
     computer. For example A system library error.

Guidelines for answering questions on the mailing list.
=======================================================

   Try to make your answer broad enough that people other than the
original poster may benefit from it. If you consider your answer to
have broad interest, you may want to post it to the mailing list
instead of replying directly to the individual who asked. In such
cases, please make sure that your answer is not a duplication of a
previous answer.

   Try to summarise the essential part of the question in your reply,
but don't feel obliged to quote the whole question.

Licensing or When do I have/want to pay for *MySQL*?
****************************************************

   Basic licensing issues:

   * The easiest way to pay for *MySQL* is to use
     TcX's secure license form (https://www.tcx.se/license.htmy).

   * You only have to pay if you are selling *MySQL* directly or
     selling a product which includes the *MySQL* server.  Unless you
     pay for a license, you may not include *MySQL* in a distribution
     if you charge for some part of it.  For internal use you do not
     have to pay us if you do not want to.

   * The client code is in the Public Domain or under the GPL
     (read-line).  You do not need a license to include client code in
     commercial programs.

   * We may add some additional functionality in the commercial
     version. The likely test candidate for this is fast compressed
     read only databases. The current server includes support to read
     such databases but not the packing tool. If we get enough revenue
     from support we will probably release this under the same license
     as the other stuff.

   * But if you like *MySQL* and want to encourage further development
     you are welcome to purchase a license or support.

   *Note Public::.

How much does *MySQL* cost?
===========================

   For normal use *MySQL* costs nothing. When you sell *MySQL* directly
or as a part of another product you have to pay for it. *Note Public::.

   The client access part of *MySQL* is in the public domain. The
command line client includes parts that is under the GNU Public License
(readline).

   These are our current license prices. All prices in US Dollars. If
you pay by credit card the currency is FIM (Finish Marks) so the prices
will differ slightly.

Number of licenses            Price/Copy             Total                  
1                             US $200                US $200                
10 pack                       US $150                US $1500               
50 pack                       US $120                US $6000               

   For high volume (OEM) purchases the following apply:

licenses               Price/Copy     Minimum at     Minimum Payment        
                                      one time                              
100-1000               $40            100            $4000                  
1000-2500              $25            200            $5000                  
2500-5000              $20            400            $8000                  

   The OEM prices require that you act as a middle-man for eventual
problems/extension requests from users. We also require that the OEM
customer has a support contract.

   If you have a low margin high volume product you can always talk to
us about other terms (for example a percent of the sale price). If you
do, please be informative about your product, pricing, market and any
other information that may be relevant.

How do I get commercial support
===============================

   A full price license includes really basic support. This means that
we are trying to answer any relevant question. If the answer is in the
documentation, we are going to direct you to the relevant
documentation. If you do not have a license/support we will probably not
answer at all.

   If you discover what we consider a real bug, we are likely to fix it
in any case. But if you pay for support we will notify you about the fix
status instead of just fixing it in a later release.

   More comprehensive support is sold separately:

Types of commercial support
---------------------------

Basic email support
...................

   One year of basic email support costs $200 (USD).

   It includes:
  1. For *MySQL* specific questions that does not belong to the *MySQL*
     mailing list (<mysql@tcx.se>) you can contact
     <mysql-support@tcx.se>. Remember to give your registration number
     and expiration date when mailing any list to ensure a quick
     response.

  2. We guarantee a timely answer for your mails.  We can't guarantee
     that we can solve all problems, but at least you will receive an
     answer if we can contact you by email.

  3. Your suggestions for the further development of *MySQL* will be
     taken into consideration. By taking email support you have already
     helped the further development of *MySQL*. If you want to have
     more input upgrade to a higher level of support.

  4. Helping with unexpected problems when installing *MySQL* from a
     binary distribution on a supported platforms.

  5. We will help you with bugs and missing features. All found bugs are
     fixed for the next *MySQL* release. If the bug is critical for
     your project, we will mail you a patch for it as soon the bug is
     fixed.  Critical bugs always have the highest priority for us, to
     ensure that they are fixed as soon as possible.

  6. This level of support does not cover installing *MySQL* from a
     source distribution.

  7. If you want us to help to optimize your system you have to upgrade
     to a higher level of support.

  8. You are entitled to upgrade to other support options for the
     difference between the prices.

Extended email support
......................

   One year of extended email support costs $1000 (USD).

   Extended basic supports contains everything in basic email support
with these additions:
  1. Your email will be dealt with before normal email support users and
     non-registered users.

  2. Your suggestions for the further development of *MySQL* will be
     taken into high consideration. Simple extensions that suit the
     basic goals of *MySQL* are implemented in a matter of days. By
     taking extended email support you have already helped the further
     development of *MySQL*.

  3. In this we include a binary version of the pack_isam tool that
     supports fast compressed read only databases (no `BLOB' or `TEXT'
     types yet). The current server includes support to read such
     databases but not the packing tool.

  4. Typical questions that are covered by extended email support are:
        * Answer and solving (within reason) questions that relates to
          (possibly) bugs in *MySQL*.  As soon as the bug is found and
          corrected, we will mail a patch of it.

        * Helping with unexpected problems when installing *MySQL* from
          a source/binary distribution on supported platforms.

        * Questions about missing features and offer hints how to go
          around them.

        * How to set up mysqld optimized for your situation.

  5. You are allowed to slightly alter *MySQL* TODO. This will ensure
     that the features you really need will be implemented sooner than
     otherwise.

  6. You are entitled to upgrade to login support for the difference
     between the different support prices.

Login support
.............

   One year of email/phone/telnet support costs $2000 (USD).

   Login supports contains everything in extended basic email support
with these additions:

  1. Your email will be dealt with even before that of extended support
     users.

  2. Your suggestions for the further development of *MySQL* will be
     taken into very high consideration. Realistic extensions that can
     be implemented in a a couple of hours and suit the basic goals of
     *MySQL* will be implemented as soon as possible.

  3. If you have a very specific problem we can try to log in on your
     system and try to solve it 'in place'.

  4. As any database vendor, we can't guarantee that we can rescue any
     data from crashed tables, but if the worst happens we will help
     you rescue as much as possible. *MySQL* has proven itself very
     reliable, but because of outside interference anything is possible.

  5. We will give you hints on how to optimize your system and your
     queries.

  6. You are allowed to call a *MySQL* developer (in moderation) and
     discuss your *MySQL* related problems.

Extended login support
......................

   One year of extended email/phone/telnet support costs $5000 (USD).

   Extended login supports contains everything in login support with
these additions:

  1. Your email has the highest possible priority.

  2. We will actively examine your system and help you optimize it and
     your queries. We may also optimize and/or extend *MySQL* to better
     suite your needs.

  3. You may also request special extensions just for you. For example
          select my_calculation(column1,column2) from database;

  4. We will provide a binary version of all important *MySQL*
     distributions for your system, as long as we can get a account on a
     similar system. In the worst case we may require access to your
     system to be able to make a binary version.

  5. If you can provide accommodation and pay for traveler fares you
     can even get a *MySQL* developer to visit you and offer you help
     with your troubles. The extended login support entitles you to one
     personal encounter, but we are (as always) very flexible towards
     our customers!

How do I pay for licenses/support ?
===================================

   Currently we can take SWIFT payments, cheques or credit cards.

   Payment should be made to:
     Postgirot Bank AB
     105 06 STOCKHOLM, SWEDEN
     
     T.C.X DataKonsult AB
     BOX 6434
     11382 STOCKHOLM, SWEDEN
     
     SWIFT address: PGSI SESS
     Account number: 96 77 06 - 3
     
     Specify: license and/or support and your name and email address.

   In Europe and Japan you can use EuroGiro (that should be cheaper) to
the same account.

   If you want to pay by cheque make it payable to "Monty Program KB".
And mail it to the address below.

     Monty Program KB
     Michael Widenius
     Gamla Skomakarbolev. 1 E 11
     00740 Helsingfors
     Finland

   If you want to pay with credit card over the Internet you can use
TcX's secure license form (https://www.tcx.se/license.htmy)

Who do I contact when I want more information about licensing/support?
======================================================================

   For commercial licensing, or if you have any questions about any of
the information in this section, please contact:

     David Axmark
     Detron HB
     Kungsgatan 65 B
     753 21 UPPSALA
     SWEDEN
     Voice Phone +46-18-10 22 80     (Swedish and English spoken)
     Fax +46-8-729 69 05             (Email *much* preferred)
     E-Mail: mysql-licensing@tcx.se

What Copyright does *MySQL* use?
================================

   There are (at least) four different copyrights on the *MySQL*
distribution.

  1. The *MySQL* specific source needed to make the `mysqlclient'
     library and programs in the `client' directory is in the public
     domain. Each file which is in the public domain has a header which
     clearly states so. This is everything in `client' directory and
     some parts of mysys, mystring and dbug libraries.

  2. Some small parts of the source (GNU getopt) are covered by the "GNU
     LIBRARY GENERAL PUBLIC LICENSE". See the `mysys/COPYING.LIB' file.

  3. Some parts of the source (GNU readline) are covered by the "GNU
     GENERAL PUBLIC LICENSE". See the `readline/COPYING' file.

  4. Some parts of the source (the regexp library) are covered by a
     Berkeley style copyright.

  5. The other source needed for the *MySQL* server is AGPL. See the
     file PUBLIC for more info.

   Our philosophy behind this is:

   - The SQL client library should be totally free so it can be
     included in commercial products without limitations.

   - People who want free access to the software we have put a lot of
     work into can have it so long they do not try to make money
     directly by distributing it for profit.

   - People who want the right to keep their own software proprietary,
     but also want the value from our work, can pay for the privilege.

   - That means that normal in-house use is FREE. But if you use it for
     something important to you, you may want to support further
     development of *MySQL* by purchasing a support license.

When may I distribute *MySQL* commercially without a fee?
=========================================================

   This is a clarification of the information in the '*MySQL* FREE
PUBLIC LICENSE'. *Note Public::.

   *MySQL* may be *used* freely, including by commercial entities for
evaluation or unsupported internal use. However, *distribution* for
commercial purposes of *MySQL*, or anything containing or derived from
*MySQL* in whole or in part, requires a written commercial license from
TcX AB, the sole entity authorised by to grant such licenses.

   You may not include *MySQL* "free" in a package containing anything
for which a charge is being made except as noted below.

   The intent of the exception provided in the second clause is to allow
commercial organisations operating an FTP server or a bulletin board to
distribute *MySQL* freely from it, provided that:

  1. The organisation complies with the other provisions of the FPL,
     which include among other things a requirement to distribute the
     full source code of *MySQL* and of any derived work, and to
     distribute the FPL itself along with *MySQL*;

  2. The only charge for downloading *MySQL* is a charge based on the
     distribution service and not one based on the content of the
     information being retrieved (i.e., the charge would be the same
     for retrieving a random collection of bits of the same size);

  3. The server or BBS is accessible to the general public, i.e., the
     phone number or IP address is not kept secret, and anyone may
     obtain access to the information (possibly by paying a
     subscription or access fee that is not dependent on or related to
     purchasing anything else).

   If you want to distribute software in a commercial context that
incorporates *MySQL* and you do *not* want to meet these conditions,
you should contact TcX AB to find out about commercial licensing.
Commercial licenses involve a payment, and include support and other
benefits. These are the only ways you legally can distribute *MySQL* or
anything containing *MySQL*: either by distributing *MySQL* under the
requirements of the FPL, or by getting a commercial license from TcX AB.

I'm want to sell a product that can be configured to use *MySQL*.
=================================================================

   I want to sell a product that can be configured to use *MySQL*
although my customer is responsible for obtaining/installing *MySQL*
(or some other supported alternative). Does one of us owe you money if
my customer chooses to use *MySQL*?

   If your product REQUIRED *MySQL* to work you would have to pay a
license. If *MySQL* just added some new features it should fall inside
normal use. For example, if using *MySQL* added logging to a database
instead of a text file it would not require a license.  This would, of
course, mean that the user has to fetch and install *MySQL* by himself.
If the program is (almost) useless without *MySQL* you would have to
get a *MySQL* license to sell your product.

I am running a commercial web server using *MySQL*.
===================================================

   Do I have to get a license for my copy?

   No you are not selling *MySQL* itself. But is this case we would
like you to purchase *MySQL* support. That is either your support of
*MySQL* or our support of you (the later is more expensive since our
time is limited).

Do I need a license to sell commercial perl/tcl/PHP etc applications?
=====================================================================

   Is your script designed for *MySQL* alone? Does it require *MySQL*
to function at all? Or is it designed for `a database' and can run
under *MySQL*, PostgreSQL, or something else?

   If you've designed it strictly around *MySQL* then you've really
made a commercial product that requires the engine, so yes, I would
think you have to pay.

   If, however, you can support any database with a base level of
functionality (and you don't rely on anything that only *MySQL*
supports) you probably DO NOT have to pay.

   It also depends on what you're doing for the client. Are you tying
into a database you expect to already exist by the time your software is
purchased?  Then you again probably don't have to pay. Or do you plan to
distribute *MySQL* or give them detailed instructions on installing it
with your software? Then you probably do.

   One thing I'd like to suggest, folks. Look, development won't last
forever if nobody pays. I agree that buying a copy for every software
user is prohibitive compared to other products available but would it
not be courtesy for commercial developers to register their OWN copy
that they develop with?

Possible future changes in the licensing.
=========================================

   We may choose to distribute older versions of *MySQL* with the GPL
in the future. However these versions will be identified as *GNU
MySQL*. Also all copyright notices in the relevant files will be
changed to the GPL.

Compiling and installing *MySQL*
********************************

How do I get *MySQL*?
=====================

   You can always check *MySQL*'s home page (http://www.tcx.se/) to see
what the latest news.

   But since the Internet connection at tcx is not to fast we would
prefer if you do the actual downloading from one of the mirrors below.

   Europe:
   * Mirror at Matrice (Italy) (http://www.matrice.it/risorse/mysql)

   * Mirror at Sunet (Sweden) (http://ftp.sunet.se/pub/unix/databases/relational/mysql/index.html)

   *
     Mirror at Wolfenbuettel (Germany) (http://www.fh-wolfenbuettel.de/ftp/pub/database/mysql/Welcome.html)

   * Mirror at Staufen (Germany) (http://mysql.staufen.de)

   * Mirror at Xenia (Hungary) (http://xenia.sote.hu/ftp/mirrors/www.tcx.se-mysql/Welcome.html)

   * Mirror at Netvision (Israeli) (http://mysql.netvision.net.il)

   * Mirror at Garant (Russia) (http://online.garant.ru/mysql)

   * Mirror at Univ. of Technology      Vienna (Austria) (http://gd.tuwien.ac.at/db/mysql)

   * Mirror at CESNET (Czech Republic) (http://mirror.opf.slu.cz/mysql)

   * FTP      to MicroMuse (UK) (ftp://ftp.micromuse.co.uk/pub/packages/unix/databases/mysql)

   * FTP to Netvision      (Israeli) (ftp://mysql.netvision.net.il/mirrors/mysql)

   * FTP to Garant (Moscow/Russia) (ftp://ftp1.garant.ru/pub/MySQL)

   * FTP to      Wolfenbuettel (Germany) (ftp://ftp.fh-wolfenbuettel.de/pub/database/mysql)

   * FTP at Sunet (Sweden) (ftp://ftp.sunet.se/pub/unix/databases/relational/mysql/index.html)

   * FTP to www.tcx.se (Sweden) (ftp://www.tcx.se/pub/mysql/).

   North America:
   * Mirror at Buoy (USA/NY) (http://www.buoy.com/mysql)

   * Mirror at IQuest (USA/Indiana) (http://mirrors.iquest.net/mysql)

   * Mirror at Tryc (Canada) (http://web.tryc.on.ca/mysql)

   * FTP at St. Louis (USA) (ftp://ftp.id.wustl.edu/pub/database/mysql)

   * FTP at Seattle (USA/West Coast)
     (ftp://ftp.netcasting.net/pub/mysql)

   Asia:
   * Mirror at Acer (Taiwan) (http://mysql.acer.net)

   * Mirror at KREONet (Korea) (http://linux.kreonet.re.kr/mysql)

   * Mirror at HappySize (Japan) (http://www.happysize.co.jp/mysql)

   * FTP at Wownet (Taiwan) (ftp://ftp.wownet.net/mysql)

   * FTP at Oneway (Taiwan) (ftp://ftp.oneway.com.tw/pub/mysql)

   * FTP at KREONet      (Korea) (http://linux.kreonet.re.kr/pub/tools/db/mysql)

   * FTP at HappySize (Japan) (ftp://ftp.happysize.co.jp/pub/mysql)

   Australia:
   * Mirror at Blue Planet NET      (Australia/Melbourne) (http://mysql.bluep.com)

   * FTP at Blue Planet NET      (Australia/Melbourne) (ftp://mysql.bluep.com/pub/mysql)

Which *MySQL* version should I use?
===================================

   The first decision is if you want to use the latest development
release or the last stable release.

   Normally if you are starting with development we recommend going with
the development release. This is because there are usually no realy bad
bugs in the development release and if you can easily test it on you
machine with the crash-me and benchmark tests. *Note Benchmarks::.

   The second decision is if you want a source of a binary release.

   If you want to run *MySQL* on a platform that has a current binary
release use that. A binary version of *MySQL* is easier to install.

   If you want to read (and/or modify) the C and C++ code that makes up
*MySQL* you should always get a source distribution. The code is always
the ultimate manual. The source distribution also contains more tests
and examples than the binary distribution.

   To clarify our naming schema:

   All *MySQL* versions is run trough our standard test and the
benchmarks to ensure that they are relatively safe to use.  The standard
test is also extended the whole time to test for all previously found
bugs, so it's gets better the whole time.

   The *MySQL* release numbers consists of 3 numbers and a suffix.

   So a release name like `mysql-3.21.17-beta' means.

The first number. In this case 3
     This describes the file format. So all version 3 releases has the
     same file format. And when a version 4 appears every table has to
     be converted to the new format (Nice tools for this will of cource
     be included).

The second number. In this case 21
     This is the release level. Normaly where is two of these to choose
     from. One is the release/stable branch and the other is the
     development branch. Normaly both are stable but the development
     version may have quirks, missing documentation and fail to compile
     on some systems.

The third number. In this case 17
     This is the version number. This is incremented for each release.
     Usually you want the latest version for the release you have
     choosen.

The suffix. In this case beta
        * Alpha means that there exists some new large code section
          that hasn't been tested to 100%, known bugs should be
          documented in the News section (usually there are none).
          There is also new commands and extensions in most alpha
          releases.

        * Beta means that all new code has been tested. No major new
          things are added anymore. There should be no known bugs.

        * Gamma is a beta that has been around a while and seems to
          work fine.  This is what many other companies call a release.

        * Release (no extension) means that the version has been run
          for a while at many different sites without any bug reports
          (Exept platform specific bugs).

   Note that all releases has at least been tested with:

A internal testsuite
     This is part of a production system for a customer. It has many
     tables and with many mega bytes of data and lots of tables.

The *MySQL* benchmark suite
     This runs a range of common queries. It is also a test to see that
     the latest batch of optimizations actually made the code faster.
     *Note Benchmarks::.

The crash-me test
     This tries to find what the database supports and which limitation
     it has. *Note Benchmarks::.

   Another test is our internal production. We usually use the latest
version for this (at least on one machine) and we have more than 100
giga byte of data to work with.

How/when will you release updates?
==================================

   We are going to use the following policy when updating *MySQL*:

   Each minor version will increment the last number in the version
string. When there are major new features or minor incompatibilities
with previous versions, the second number in the version string will be
incremented. When the file format changes the first number will be
increased.

   * Stable tested releases are meant to appear about 1-2 times a year.
     But if small bugs are found a release with only bug fixes will be
     released.

   * Working releases are meant to appear about every 1-8 weeks.

   * Binary releases for some platforms will be make for major releases
     by us. Other people may make binary releases for other systems but
     probably less frequently.

   * We usually make patches available as soon as we have located and
     fixed small bugs.

   * For non-crucial but annoying bugs we will make patches available
     if they are sent to us, otherwise we will combine many of them
     into a bigger patch.

Which operating systems does *MySQL* support?
=============================================

   We use GNU autoconf so it will be possible to port to all modern
systems with working Posix threads and a C++ compiler. The client code
requires C++ but not threads. We use/develop the software ourselves
primarily on Sun Solaris (version 2.5 & 2.6) and some on RedHat Linux
5.0.

   The following OS/thread package's has been reported to compile
*MySQL* successfully. Note that for many OSes the native thread support
only works in the latest versions.

   * Solaris 2.5 & 2.6 with native threads.

   * BSDI 3.1 native threads.

   * SGI IRIX 6.x with native threads.

   * AIX 4.x whith native threads.

   * DEC UNIX 4.x with native threads.

   * Linux 2.0+ with LinuxThreads 0.5,0.6 and 0.7.

   * FreeBSD x.x with the included MIT threads package.

   * SCO OpenServer with a recent port of the FSU-threads package.

Compiling *MySQL* from source code.
===================================

   What you need:

  1. GNU `gzip' to uncompress the distribution.

  2. A reasonable `tar' to unpack the distribution. GNU `tar' is known
     to work.

  3. A working ANSI `C++' compiler. gcc >= 2.7, SGI C++, SunPro C++ are
     some of the compilers that are known to work. `libg++' is not
     needed when using `gcc'.

  4. A good make program. If you have problems we recommend trying GNU
     `make'.

Quick installation overview.
----------------------------

   Unpack tar archive in a directory. The tar file should be named like
mysql-VERSION.tar.gz (VERSION is a number like 3.21.18a-beta). A
directory named mysql-VERSION should be created.

`zcat mysql-VERSION.tar.gz | tar xvf -'
     Unpack the distribution into the current directory.

`cd mysql-VERSION'
     Change directory.

`./configure'
     Configure the release. Here you might want to add some options.
     For a list of configure options use `./configure --help'.

`make'
     Compile everything.

`make install'
     Install everything.

`./scripts/mysql_install_db'
     Set up the *MySQL* privilige tables. This only needs to be done
     the first time you install *MySQL*. You may want to edit this
     script before running it to get right initial permissions for
     users to connect to the database.

`'installation_directory'/bin/mysqladmin version'
     Check to see if the server is running. Unless you added some
     options to `./configure' 'installation_directory' is `/usr/local'.
     Here is a example of the output you should get (You will not get
     this exactly!):
          mysqladmin  Ver 6.3 Distrib 3.21.17, for pc-linux-gnu on i686
          TCX Datakonsult AB, by Monty
          
          Server version          3.21.17-alpha
          Protocol version        10
          Connection              Localhost via UNIX socket
          TCP port                3306
          UNIX socket             /tmp/mysql.sock
          Uptime:                 16 sec
          
          Running threads: 1  Questions: 20  Reloads: 2  Open tables: 3

   Usual configure switches:
   * To compile only the client use `--without-server'

   * If you don't want to have your data under `/usr/local/var' use
     something like: `--prefix=/usr/local' or `--prefix=/usr/local
     --localstatedir=/usr/local/data/mysql'

   * If you don't want to have your sockets in the default place
     (Default is `/tmp' or `/var/run') use
     `--with-unix-socket-path=absolute_file_name'

   * Changing the default character set.

     By default *MySQL* will use the ISO8859-1 (Latin1) character set.
     You may change this at compile time by the configure swithc
     `--with-charset=charset'.

     Where [charset] may be one of: `big5', `czech', `dec8', `dos',
     `german1', `hp8', `koi8_ru', `latin1', `latin2', `swe7' or `usa7'.

     If you want to add another character set to *MySQL* you must:
        * Choose a name. CHARSET_NAME

        * Create the file
          `mysql_source_directory/strings/ctype-$CHARSET_NAME.c'.

        * Look at one of the existing ctype files to see what needs to
          be defined. Note that the arrays in this file must have names
          like ctype_$CHARSET_NAME, to_lower_$CHARSET_NAME and so on.

        * Add charset name to `CHARSETS_AVAILABLE' list in
          `configure'.in

        * Recompile and test

     *Warning:* If you change character sets after having created a
     table you will have to run `isamchk -r -q' on every table.
     Otherwise things will be sorted incorecctly in some cases (but not
     all!).

   * For computer/OS specific switches see the menu later in this
     chapter.

   GNU `make' is always recommended and sometimes required.

   About creating the grants database `mysql_install_db':

   The default priviliges is that anybody may create/use the databases
named `test' or starting with `test_'. `root' can do anyting. *Note
Privileges::.

   To change the defaults edit the script before running it.  If this is
the first time you install *MySQL* you must run this command. If you
don't do it you will get the error: `Can't find file:
'./mysql/host.frm''. This script also starts the mysqld daemon the first
time.

   Normal start of the *MySQL* server demon (not needed the first
time): `'installation_directory'/bin/safe_mysqld --log'

Applying a patch
----------------

   Some times patches appear on the mailing-list. To apply on do
something like this:

     cd 'old-mysql-source-distribution-path'
     gunzip < patch-file-name.gz | patch -p1
     
     rm config.cache
     make clean

   And then follow the instructions for a normal source install from the
`./configure' step.

   And the restart your *MySQL* server.

Problems compiling ?
====================

   If your compile fails with something like:

     configure: error: installation or configuration problem: C++ compiler
     cannot create executables.

   Try setting the environment variable `CXX' to `"gcc -O3"' (If you
are using `gcc').  For example `CXX="gcc -O3" ./configure'. If you use
this you don't nead to have libg++ installed!

   You can also install libg++. By default `configure' picks `c++' as a
compiler name and GNU `c++' links with `-lg++'.

  1.      making all in mit-pthreads
          make: Fatal error in reader: Makefile, line 18: Badly formed macro assignment
     This means you have to upgrade your make to GNU make.

  2. If you want to add flags to your C or C++ compiler add the flags
     to the CC and CXX environment variables. For example:

          CC="gcc -O4"
          CXX="gcc -O4"
          export CC CXX

  3. If your make stops with `Can't find Makefile.PL' when making
     mysqlperl you should try using GNUx make. At least Solaris and
     FreeBSD is known to have troublesome make programs.

  4. If you get error messages from make or error message of type:
     `pthread.h: No such file or directory'

     This means you have to upgrade your make to GNU make (At least GNU
     make version 3.75 works).

  5. If you get a error message like: `client/libmysql.c:273: parse
     error before `__attribute__''

     This means you need to upgrade your gcc compiler (2.7.2 is known
     to work).

  6. If configure fails, and you are going to mail <mysql@tcx.se>,
     please include any lines from config.log that you think can help
     solve the problem.  Include also a couple of lines of the last
     output from configure if configure aborts. Post the bug with the
     script 'mysqlbug'.

     *PLEASE ALWAYS USE `mysqlbug'* when posting questions to
     <mysql@tcx.se>. *Note Bug reports::.

     Even if the problem isn't a bug, mysqlbug gathers some system
     information that will help other solve your problem!

  7. If you need to debug mysqld or a *MySQL* client, run configure
     with: `configure --with-debug=yes'

     Before running a client you should do:
          MYSQL_DEBUG=d:t:o,/tmp/client.trace
          export MYSQL_DEBUG

     You will now get a trace file in `/tmp/client.trace'.

  8. If you have problem with your own client code, test first with
     `mysql --debug=d:t:o,/tmp/client.trace' before mailing a bug
     report. *Note Bug reports::.

  9.  If you get three errors when compiling mysqld like:
            cxx: Error: mysqld.cc, line 645: In this statement, the referenced type of
                 the pointer value "&length" is "unsigned long", which is not compatible
                 with "int".
            new_sock = accept(sock, (struct sockaddr *)&cAddr, &length);

     Then configure didn't detect the type of the last argument to
     `accept()', `getsockname()' and `getpeername()'.  Search after the
     line:

          /* Define as the base type of the last arg to accept */
          #define SOCKET_SIZE_TYPE ###

     and change ### to size_t or int depending on your operating system.

General compilation notes
=========================

   All *MySQL* programs compile clean (no warnings) for us (on Solaris
using gcc). But warning may appear because of different system include
files. Se below for warnings that may occur when using mit-pthreads.

   When compiling sql_yacc.yy you should probably get:
     conflicts:  4 reduce/reduce

   You probably have to use bison to compile sql_yacc.yy. If you get an
error like:
     "sql_yacc.yy", line xxx fatal: default action causes potential...
   you have to install bison (the gnu yacc).

   If you want to have static linked code, use (with gcc):
`LDFLAGS="-static" ./configure ...'

MIT-pthreads notes. (FreeBSD)
=============================

   Building in a non source directory is not supported when using
MIT-threads. This is because we want to keep our changes to this code
minimal.

   MIT-pthreads doesn't support the `AF_UNIX' protocol so we must use
the TCP/IP protocol for all connections (which is a little slower).  If
you can't connect to a table, try using the host (`-h' or `--host')
switch to `mysql'.  This must be done if you have compiled the client
code `--without-server' because the default connection is to use Unix
sockets.

   *MySQL* compiled with MIT threads has as default system locking
disabled for performance reasons. One can start the server with system
locking with the `--use-locking'.

   Sometimes (at least on Solaris) the pthread `bind()' command fails
to bind to a socket without any error message. The result of this is
that all connections to server fails.

     > mysqladmin ver mysqladmin: connect to server at '' failed;
         error: 'Can't connect to mysql server on localhost (146)'

   The solution to this is to kill the `mysqld' demon and restart it.
This has only happened to us when we have forced the demon down and done
an restart directly.

   `sleep()' isn't interruptible with `SIGINT' (break) with
MIT-threads. This is only notable in `mysqladmin --sleep'. One have to
wait for the end of the sleep before the interrupt is served and the
process stops.

   We haven't got readline to work with MIT threads. (This isn't needed,
but may be interesting for someone)

   When linking (at least on Solaris) you will receive warning messages
like:

     ld: warning: symbol `_iob' has differing sizes:
     	(file /my/local/pthreads/lib/libpthread.a(findfp.o) value=0x4;
     file /usr/lib/libc.so value=0x140);
     	/my/local/pthreads/lib/libpthread.a(findfp.o) definition taken
     ld: warning: symbol `__iob' has differing sizes:
     	(file /my/local/pthreads/lib/libpthread.a(findfp.o) value=0x4;
     file /usr/lib/libc.so value=0x140);
     	/my/local/pthreads/lib/libpthread.a(findfp.o) definition taken

   Some other warnings which also can be ignored:

     implicit declaration of function `int strtoll(...)'
     implicit declaration of function `int strtoul(...)'

Perl installation comments.
===========================

   The included perl client code requires perl5.004 or later.

   If you got a the following error (from mysqlperl or DBD-mysql):

     /usr/bin/perl: can't resolve symbol '__moddi3'
     /usr/bin/perl: can't resolve symbol '__divdi3'

   You are probably using gcc (or using a old binary compiled with
gcc). Add `-L/usr/lib/gcc-lib/... -lgcc' to the link command where
`-L/...'  is the path to the directory where `libgcc.a' exists.

Special thing to consider with some machine/OS combinations.
============================================================

Solaris notes.
--------------

   Sun native threads only works on Solaris 2.5 and higher. For 2.4 and
earlier versions you can use MIT-pthreads. *Note MIT-pthreads::.

   If there is too many processes that tries to connect very rapidly to
the `mysqld' one will get `Error in accept : Protocol error' in the
mysql log.

   If you have the Sun Workshop 4.2 compiler you can configure with:
`CC="cc -Xa -fast -xstrconst" CXX="CC -xsb -noex -fast" ./configure'

   You may also have to change the row in configure:

   `#if !defined(__STDC__) || __STDC__ != 1' to `#if
!defined(__STDC__)' because if you turn on `__STDC__' with the `-Xc'
switch, the Sun compiler can't compile with the Solaris `pthread.h'
header files anymore. This is a Sun bug (Broken compiler or broken
include file).

SunOS 4 notes.
--------------

   On SunOS 4 MIT-pthreads is needed. You must have gnu make to compile
(because of MIT-pthreads).

   In readline you may get warnings about duplicated defines. These may
be ignored.

   When compiling mysqld there will be some warnings about `implicit
declaration of function'. These may be ignored.

Linux notes for all versions
----------------------------

   On Linux you should (it is added automatically by `safe_mysqld') use
the `--skip-locking' flag to `mysqld'. This is because a bug in Linux
file locking calls. This error has been verified to still exists in
Linux version 2.0.32.

   When using LinuxThreads you will see a minimum of three processes
running. These are in fact threads. There will be one thread for the
Linux Threads manager, one thread to handle connections, and one thread
to handle alarms and signals.

Linux-x86 notes.
................

   LinuxThreads should be installed before configuring *MySQL*!

   *MySQL* libc version 5.4.12 or newer. glibc version 2.0.6 and later
should also work.

   On some older Linux distributions `configure' may give a error
about: `Syntax error in sched.h. Change _P to __P in the
/usr/include/sched.h file.\  See the Installation chapter in the
Reference Manual'. Just do what the error says and add a extra
underscore to the `_P' macro that only has one underscore. And then try
again.

   You will get some warnings when compiling: (these can be ignored)

     mysqld.cc -o objs-thread/mysqld.o
     mysqld.cc: In function `void init_signals()':
     mysqld.cc:315: warning: assignment of negative value `-1' to `long unsigned int'
     mysqld.cc: In function `void * signal_hand(void *)':
     mysqld.cc:346: warning: assignment of negative value `-1' to `long unsigned int'

   When using glibc 2 you must also execute the configure with `CXX=gcc
./configure ...' because if you compile with g++, you will link with
libg++ which dosen't work with LinuxThreads.

   If you want in Debian GNU/Linux to get *MySQL* to auto start when
system boots, do the following:

     > cp scripts/mysql.server /etc/init.d/mysql.server
     > /usr/sbin/update-rc.d mysql.server defaults 99

   There is a bug in glibc 2.0.5 in how pthread_key_create variables are
freed.  With glibc2 2.0.5 (For example on RedHat 5.0 systems) you have
to use the staticly linked *MySQL* binary distribution.

   If mysqld always does a core dump when starting, the problem may be
that you have and old `/lib/libc.a'.  Try renaming this, remove
sql/mysqld and do a new make install and try again.  This problem has
been reported on some Slackware installations.

Linux-Sparc notes.
..................

   In some implementations `readdir_r' is broken.  This will be notised
by that `SHOW DATABASES' always return an empty set.  This can be fixed
by removing `HAVE_READDIR_R' from `config.h'.

   If you get problems you probably have to apply a patch to your Linux
installation.  The patch can be got at
`http://www.tcx.se/patches/Linux-sparc-2.0.30.diff'. This patch is
against the linux distribution `sparclinux-2.0.30.tar.gz', that is
available at vger.rutgers.edu.  This is a version of linux which was
never merged with the official 2.0.30.  You also have to install
linuxthreads 0.6 or newer.

   Thanks to jacques@solucorp.qc.ca for the above information.

Linux-Alpha notes.
..................

   The first problem is linuxthreads.  You must patch linuxthreads for
alpha because the RedHat distribution uses an old (broken) linuxthread
version.

  1. Get hold of the glibc2.5c source from any gnu ftp site.

  2. Get the file



     `ftp://www.tcx.se/pub/mysql/linux/patched-glibc-linuxthreads-0.6.tgz'.
     This includes a fixed .c file.  Copy this to the glibc
     `./linuxthreads' directory.

  3. Configure and compile glibc (You have to read the manual how to do
     this together with linuxthreads). Don't install this!

  4. Rename your old version of /usr/lib/libpthread.a to
     /usr/lib/libpthread.a-old

  5.  6. Copy the file glibc.../linuxthreads/libpthread.a to /usr/lib.

  7. Try to compile mysys/thr_lock and mysys/thr_alarm.  Test that these
     works!

  8. Recompile mysqld.

   Note that Alpha-Linux is still an alpha platform for MySQL.  With
RedHat 5.0 and the patched linuxthreads you have a very good change to
get this to work.

Alpha-DEC-Unix notes.
---------------------

   When compiling threaded programs under Digital UNIX using CC / CXX
the documentation recommends the switch to cc and cxx and the libraries
`-lmach -lexc' (in addition to `-lpthread').

   So you have to configure with something like this:

   `CC="cc -pthread" CXX="cxx -pthread -O" ./configure
-with-named-thread-libs="-lpthread -lmach -lexc -lc"'

   When compiling mysqld you will may this warning for mysqld for a
couple of lines:

     mysqld.cc: In function void handle_connections()':
     mysqld.cc:626: passing long unsigned int *' as argument 3 of accept(int,sockad
     ddr *, int *)'

   You can safely ignore these. This is because configure can't detect
warnings, only errors.

   You may get problems with the server exiting directly. If so try
starting it with `nohup safe_mysqld [options]'

   `nohup' is a command that ignores any `SIGHUP' sent from the
terminal.

Alpha-DEC-OSF1 notes.
---------------------

   In some versions of OSF1 the `alloca()' functions is broken. Fix
this by remove `'HAVE_ALLOCA'' from config.h.

   When using the Digital C++ you could try
`-with-named-thread-libs="-lpthread -lmach -lexc -lc"'

SGI-IRIX notes.
---------------

   You may have to undefine some things in `config.h' (generated by
`./configure').

   In some Irix implementations the `alloca()' function is broken. If
the mysqld server dies on some selects remove `HAVE_ALLOC' &
`HAVE_ALLOCA_H' from `config.h'.  If mysqladmin create doesn't work,
remove `HAVE_READDIR_R' from config.h. Also you may have to remove
`HAVE_TERM_H'.

   Irix 6.2 doesn't support POSIX threads out of of the box.  You have
install these patches, available from SGI if you have support:

   1403, 1404, 1644, 1717, 1918, 2000, 2044

   If you get the something like the following error when compiling
mysql.cc:

     "/usr/include/curses.h", line 82: error(1084): invalid combination of type

   type the following in the mysql installation directory:

     > extra/replace bool curses_bool < /usr/include/curses.h > include/curses.h
     > make

   There has also been reports about scheduling problems. This is if
only one thread is running things go slow. Avoid this by starting
another client. This may lead to a 2-10 fold increase in execution speed
hereafter for the other thread.

   This is a badly understood problem with IRIS threads so you may have
to improvise to find solutions until it can be fixed.

FreeBSD notes.
--------------

   If you get link errors when compiling mysqlperl (Type
`ient.a(my_getwd.o): RRS text relocation at 0x9a9f for "__db_pargs_"')

   You must recompile the Perl code with `-DPIC -fpic'.

   Do the following:

  1. First install everything.

  2. Change in `client/Makefile' the line: `CFLAGS = -g -O2' to `CFLAGS
     = -O2 -DPIC -fpic'

  3. `cd client'

  4. `rm *.o'

  5. `make libmysqlclient.a'

  6. `cd ../perl/mysqlperl'

  7. `make'

   This shall hopefully be handled automatically in the future.

   The FreeBSD make behaviour is slightly different from GNU makes. If
you have a problem that `mysqlperl/Makefile.PL'x doesn't get generated
you should install GNU make.

   Other (temporary) solution:
     > cd perl
     > make mysqlperl/Makefile.PL
     > make mysqlperl/mysql_test

   If you get `ERROR Can't create/write to file 'xxx.ISD' error 23'
from *MySQL* this means that you haven't allocated enough file
descriptors for *MySQL*. `perror #' will give you the error message in
a more readable form.

   There is commented line `ulimit -n 256' in `safe_mysqld'. You can
remove this comment and of course increase or decrease the value if you
want. You can also make the table cache smaller with: `safe_mysqld -O
table_cache=32' (the default is 64).

   If mysql or mysqladmin takes a long time to respond a user said the
following.

   Are you running the ppp user process? On my FreeBSD box (2.2.5) MySQL
clients takes a couple of seconds to connect to mysqld if the ppp
process is running.

FreeBSD-3.0 notes.
..................

   You have to configure with:

   `--with-named-thread-libs=-lc_r'

   The pthreads library for FreeBSD doesn't contain the `sigwait'
function and there is some bugs in it.  To fix this, get the
`FreeBSD-3.0-libc_r-1.0.diff' file and apply this in the
`/usr/src/lib/libc_r/uthread' directory. Follow after this the
instructions that can be found with `man pthread' about how to
recompile the `libc_r' library.

   You can test if you have a 'modern' `libpthread.a' with:

     > nm /usr/lib/libc_r.a | grep sigwait.

   If the above doesn't find `sigwait' you have to use the above patch
and recompile `libc_r'.

BSDI 2.# notes
--------------

   From Jan Legenhausen <jleg@csl-gmbh.net>.

   I finally got mysqlperl working on BSDI2.1.

   What i did was almost nothing:
  1. cd client

  2. Leave the Makefile as it is! (i use `GCC="shlicc2"' per default;
     perl5 automagically uses shlicc2 - you should use _one_ version
     (either `gcc' or `shlicc2') for both `Mysql.c' and
     `libmysqlclient.a'!)

  3. `rm *.o'

  4. `gmake libmysqlclient.a'

  5. `cd ../perl/mysqlperl'

  6. `make clean'

  7. add `$sysliblist=" -L$tmp -lgcc -lcompat";' to Makefile.PL line 45
     (just to be sure - i didn't check if one could leave out this one)

  8. `perl Makefile.PL'

  9. remove all old `libmysqlclient.a''s in `/usr/lib' and
     `/usr/contrib/lib'

 10. `make install'

   If you can't run the `mysql_install_db' script because the script
can't connect to the server you should check that you have an entry in
/etc/hosts like:

   127.0.0.1		localhost

   If you get the following error when compiling *MySQL*:

     item_func.h: In method `Item_func_ge::Item_func_ge(const Item_func_ge &)':
     item_func.h:28: virtual memory exhausted
     make[2]: *** [item_func.o] Error 1

   Then your ulimit for virtual memory is too low. Try using: `ulimit
-v 30000' and do `make' again.

BSDI 3.# notes.
...............

  1. Upgrade to BSD/OS 3.1. If that is not possible, install BSDIpatch
     M300-038.

  2. Use the following configuration when installing *MySQL*:
          env CXX=shlicc++ CC=shlicc2 ./configure --prefix=/usr/local
          --localstatedir=/var/mysql --without-perl
          --with-unix-socket-path=/var/mysql/mysql.sock

   You can change the directory locations if you wish, or just use their
defaults by not specifying them.

SCO notes.
----------

   The current port is only tested on a 'sco3.2v5.0.4' system.

  1. For OpenServer 5.0.X You need to use GDS in Skunkware 95 (95q4c).
     This is necessary because GNU gcc 2.7.2 in Skunkware 97 do not
     have the GNU as.

  2. You need the port of GCC 2.5.? for this product and the
     Developement system.  They are required on this version of SCO
     UNIX.  You can not just use the GCC Dev system.

  3. One should get FSU thread package and install this first.  This
     can be found at:
     `http://www.cs.wustl.edu/~schmidt/ACE_wrappers/FSU-threads.tar.gz'
     You can also get a precompiled package from:
     `ftp://www.tcx.se/pub/mysql/SCO/fsu-threads.tar.gz'

  4. FSU pthreads can be compiled with SCO UNIX 4.2 with tcpip.  Or
     OpenServer 3.0 or Open Desktop 3.0 (OS 3.0 ODT 3.0), with the SCO
     Developement System installed using a good port of GCC 2.5.X ODT
     or OS 3.0 you will need a good port of GCC 2.5.? There are a lot
     of problems with out a good port.  The port for this product
     requires the SCO UNIX Developement system.  You are missing the
     libraries and the linker that is needed.

  5. To build FSU pthreads in your system do the following:
       1. Run ./configure in threads/src directory and select the SCO
          OpenServer option. This command copy Makefile.SCO5 to
          Makefile.

       2. Run make.

       3. To install in default /usr/include directory, login as root
          and cd to thread/src directory, run make install.

  6. Remember to use gnu make when making *MySQL*.

  7. If you don't start safe_mysqld as root, you vill probably only get
     the default 110 open files per process.  mysqld will write a note
     about this in the log file.

   SCO development notes:

   * *MySQL* configure will automaticly adds the -belf flag to CC and
     CXX if you are using gcc.

   * *MySQL* should automaticly detect FPU-threads and link mysqld
     with: `-lgthreads -lsocket -lgthreads'

   * The SCO development libraries are reentrant in FSU pthreads. SCO
     claims that its libraries function are reentrant so they must be
     reentrant with FSU pthreads. FSU pthreads on OpenServer tries to
     use the SCO scheme to make reentrant library.

   * FSU threads (at least the version at www.tcx.se) comes linked with
     gnu-malloc.  If you get problems with memory usage, check that
     gmalloc.o is included in libgthreads.a and libgthreads.so

   * In FSU pthreads the following system calls are pthread aware: read,
     write, getmsg, connect, accept, select and wait.

IBM-AIX notes.
--------------

   When using THE IBM compiler something like this is needed.

     CC="xlc_r -ma -O3 -qstrict" CXX="xlC_r -ma -O3 -qstrict" ./configure

   Automatic detection of xlC is missing from autoconf.

Installation instructions for *MySQL* binary release
====================================================

   PLEASE always use the mysqlbug script when posting questions to the
mailinglist (<mysql@tcx.se>). Even if the problem isn't a bug, mysqlbug
gathers some system information that will help other solve your
problem! *Note Bug reports::.

  1. Get a distribution. That is a file called something like
     mysql-version-OS.tgz. For example a file holding a *MySQL* version
     3.21.15 for a intel linux machine is called
     `mysql-3.21.15-alpha-pc-linux-gnu-i586.tgz'.

  2.  Pick a directory to put *MySQL* in: In the following we will use
     `/usr/local/mysql' as the installation directory and *MySQL*
     version VERSION (something like 3.21.15) for SunOS5 (Solaris) as an
     example.

  3.  All of the following instructions assume you have permission to
     create files in `/usr/local'.

     Use the following commands to create the directory and unpack the
     distribution:

          > cd /usr/local
          > zcat /<where ever you put it>/mysql-3.20.0-SunOS5.tgz | tar xvf -
          > ln -s mysql-VERSION mysql

  4. After this you should install the *MySQL* privilige tables.

     In some binary versions the grant tables may already be created,
     for others distributions you should edit the
     `scripts/mysql_install_db' script to have the privileges you want
     and run it. The default privileges is that anybody may create/use
     the databases named 'test' or starting with "test_". The *MySQL*
     user root can do anything. Note that you do not have to run the
     *MySQL* server as root. Any user is ok as long as it can read and
     write in the installtion directories/files.

     If you want to recreate the privilege tables remove all the *.ISM
     and  *.ISD files in the mysql database directory, edit the
     scripts/mysql_install_db script to have the privileges you want
     and run it.

     This creates the privilige tables if they don't exist:
          > scripts/mysql_install_db

     The `mysql_install_db' script also starts the `mysqld' demon.

  5. Normal start the *MySQL* server demon (not needed the first time):

          > bin/safe_mysqld --log &

  6. You can test that the demon is running by running this:

          > bin/mysqladmin ver

     That should print something like this. The exact output depends on
     you platfrom and use.
          bin/mysqladmin  Ver 6.3 Distrib 3.21.15-alpha, for SOLARIS 2.5 on SPARCstation
          TCX Datakonsult AB, by Monty
          
          Server version          3.21.15-alpha
          Protocol version        9
          Connection              Localhost via UNIX socket
          TCP port                3306
          UNIX socket             /tmp/mysql.sock
          Uptime:                 2 days 1 hour 42 min 3 sec
          
          Running threads: 2  Questions: 450378  Reloads: 17  Open tables: 64

To get perl work do the following:
----------------------------------

     > cd mysqlperl
     > perl Makefile.PL
     > make
     > make install

   You should use the `safe_mysqld' script to the server.
`safe_mysqld' expects one of two conditions to be true:

  1. You're executing the script from the base mysql installation
     directory (for example `/usr/local/mysql')

  2. The server should resides in `/my/'.  To get it to run correctly,
     you should cd to `/usr/local/mysql' and then execute `safe_mysqld'
     or modify the script so that it expected the base mysql directory
     to be `/usr/local/mysql' rather than the default `/my/'.

   By executing

     > bin/mysqld --help

   you will get the options for mysqld (and safe_mysqld) and the current
paths. Normally you only should need to change the `--basedir=path'.
You can test the path switches by executing:

     > bin/mysqld --basedir=/usr/local --help

   If you would like to use mysqlaccess and have the mysql distribution
in some nonstandard place you have to change the path to mysql in
mysqlaccess. `bin/mysqlaccess' about line 308:

     $MYSQL = '/usr/local/bin/mysql --batch --unbuffered';

   If you don't change the path you will get a 'broken pipe' error when
using mysqlaccess.

   If you would like *MySQL* to start when you boot your machine, you
can copy `bin/mysql.server' to where your system has it startup files.
More information can be bound in the bin/mysql.server script itself.

LINUX notes.
------------

   * MySQL needs at least Linux 2.0.

   * The binary distribution may need LinuxThread.  If you get an error
     like: 'libpthread.so.0 not found', you have to install
     LinuxThreads.  You can find a copy of linuxthreads at:
     http://www.tcx.se//

   * The perl distribution needs perl5.003

HPUX notes.
-----------

   The binary distribution of *MySQL* for HP-UX is distributed as an HP
depot file.  This means that you must be running at least HP-UX 10.x to
have access to HP's software depot tools.

   This version of *MySQL* was compiled on an HPUX 9000/8xx server
under HP-UX 10.20, and uses MIT Pthreads. It is known to work, and work
well under this configuration. This version does *not* use HP's native
thread package. It is highly unlikely that *MySQL* will use HP native
threads on anything but HP-UX 10.30 or later.

   Other configurations that may work:

   9000/7xx - HP-UX 10.20+ 9000/8xx - HP-UX 10.30 (does not use HP
native threads)

   The following configurations almost definately wont work:

   9000/7xx or 8xx - HP-UX 10.x where x < 2 9000/7xx or 8xx - HP-UX 9.x

   To install (everything, incl server, client and devel tools):

   /usr/sbin/swinstall -s <full path to the depot file> mysql.full

   To install server only:

   /usr/sbin/swinstall -s <full path to the depot file> mysql.server

   To install client pack only:

   /usr/sbin/swinstall -s <full path to the depot file> mysql.client

   To install developers tools only:

   /usr/sbin/swinstall -s <full path to the depot file> mysql.developer

   The depot will place binaries/libraries in /opt/mysql and data in
/var/opt/mysql. The depot will also create the appropriate entries in
/sbin/init.d and /sbin/rc2.d to automatically start the server on boot.
This would obviously entail being root to install.

Linking client libraries
------------------------

   Clients have to be linked with: `-lmysqlclient'

Problems starting *MySQL*
=========================

   Check the log file to see if mysqld started up correctly.

   `mysqld' demon starts with a cd to 'mysql-data-dir'. After this,
mysqld-data-dir is changed to './' (current dir). All paths (databases,
pid file, and log file) have this directory as base path './'. If you
have any problems with wrong paths, try `mysqld --help' to see your
current paths. Every path can be changed by a startup option to
`safe_mysqld' or `mysqld'

     cd <localstatedir default /usr/local/var>
     tail <your host name>.log

   To verify that *MySQL* is working run the following tests:

     > cd /usr/local/bin
     > ./mysqlshow
     +-----------+
     | Databases |
     +-----------+
     | mysql     |
     +-----------+
     
     > ./mysqlshow mysql
     Database: mysql
     +--------+
     | Tables |
     +--------+
     | db     |
     | host   |
     | user   |
     +--------+
     
     > ./mysql -e "select host,db,user from db" mysql
     +------+--------+------+
     | host | db     | user |
     +------+--------+------+
     | %    | test   |      |
     | %    | test_% |      |
     +------+--------+------+

   There is also a benchmark suite so you can compare how *MySQL*
perform on different platforms. In the near future this will also be
used to comapre *MySQL* to other SQL databases.

     > cd bench
     > run-auto-increment-test

   You can also run the tests in the test subdirectory. To run
`auto_increment.tst':

     ./mysql -vf test < ./tests/auto_increment.tst

   Expected results are shown in the file `./tests/auto_increment.res'.

Automatic start/stop of *MySQL*
===============================

   To start or stop *MySQL* use the following commands:

     scripts/mysql.server stop
     scripts/mysql.server start

   You might want to add these start and stop commands in the
appropriate places in your `/etc/rc*' files when you start using *MySQL*
for production applications.

How standards compatible are *MySQL*
************************************

What extension has *MySQL* to ANSI SQL92?
=========================================

   The following are useful extensions in *MySQL* that you probably
will not find in other SQL's.  Be warned that if you use them, your code
will not be portable to other SQL servers.

   * The field types `MEDIUMINT', `SET', `ENUM' and the different
     `BLOB' and `TEXT' types.

   * The field attributes `AUTO_INCREMENT', `BINARY', `UNSIGNED' and
     `ZEROFILL'.

   * *MySQL* maps all tables to filenames and with *MySQL* one can use
     standard system tools to backup, rename, move, delete and copy
     tables.  This forces *MySQL* to be case sensitive on table names
     on operating systems that have case sensitive filenames (like most
     Unix systems). If you have a problem remembering table names,
     create everything in lowercase.

   * Use of `INTO OUTFILE' and `STRAIGHT_JOIN' in a `SELECT' statement.
     *Note Select::.

   * `EXPLAIN SELECT' to get a description on how tables are joined.

   * Use of index names, indexes on a subpart of a field, and use of
     `INDEX' or `KEY' in a `CREATE TABLE' statement. *Note Create
     table::

   * Use of `DROP column' or `CHANGE column' in a `ALTER TABLE'
     statement. *Note Alter table::.

   * Use of `LOAD DATA INFILE'. This syntax is in many cases compatible
     with Oracles `LOAD DATA INFILE'. *Note Load::.

   * Using `"' instead of `'' to enclose strings.

   * Using the escape `\' character.

   * The `SET OPTION' statement. *Note Set option::

   * Using, in the `SELECT' part of a `GROUP BY' statement, fields or
     functions that do not appear in the `GROUP BY' list.  In *MySQL*
     this means 'any matching value'. By using this one can get a much
     higher performance by avoiding sorting and grouping unnecessary
     items.  This is often used in this context:
          SELECT order.custid,customer.name,max(payments) from order,customer
          WHERE order.custid = customer.custid GROUP BY order.custid;
     In ANSI SQL you would have to add the customer.name in the `GROUP
     BY' clause which is redundant in *MySQL*.

   * To make it easier for user that comes from different SQL
     environments mysql supports a lot of aliases for many functions.
     For example all string functions support both the ANSI SQL and the
     ODBC syntax.

   * The `||' and `&&' operators is in *MySQL* synonyms for `OR' and
     `AND', like in the C programming language.  Likewise `|' and `&'
     stands for bitwise `OR' and `AND'.  Because if this nice syntax,
     *MySQL* doesn't support the ANSI SQL operator `||' for string
     concatenation, and one has to use `CONCAT()' instead. As
     `CONCAT()' takes any number of arguments it's easy to convert use
     of the `||' operator to *MySQL*.

   * Use of any of the following functions or commands:
        * `CREATE DATABASE' or `DROP DATABASE'.  *Note Create database::

        * `%' instead of mod().  `%' is supported for C programmers and
          for compatibility with postgreSQL.

        * `=', `<>', `<=' ,`<', `>=',`>', `AND', `OR', or `LIKE' in a
          column statement

        * `LAST_INSERT_ID'.  *Note mysql_insert_id::

        * `REGEXP' or `NOT REGEXP'.

        * `CONCAT()' or `CHAR()' with 1 or more than 2 arguments.  In
          *MySQL* they can take any number of arguments.

        * `BIT_COUNT()', `ELT()', `FROM_DAYS()', `FORMAT()', `IF()',
          `PASSWORD()', `ENCRYPT()', `PERIOD_ADD()', `PERIOD_DIFF()',
          `TO_DAYS()', or `WEEKDAY()'.

        * Use of `TRIM' to trim substrings. ANSI SQL only supports
          removal of single characters.

        * The `STD()', `BIT_OR' and `BIT_AND' group functions.

        * Use of `MIN()' or `MAX()' as normal functions, not only group
          functions.

        * Use of `REPLACE' instead of `DELETE' + `INSERT'.  *Note
          Replace::

What functionality is missing in *MySQL*.
=========================================

   The following functionality is missing in the current version of
*MySQL*.  For the priority of new extensions you should consult:
The *MySQL* Todo list
(http://www.tcx.se/Manual_split/manual_Todo.html). That is the latest
version of the Todo list in this manual. *Note Todo::.

Sub-selects
-----------

   The following will not work in *MySQL*:

     SELECT * from table WHERE id IN (SELECT id from table2)

   MySQL only supports `INSERT ... SELECT...' and `REPLACE ...
SELECT...'. Independent sub-selects will be probably be availably in
3.22.0.  One can now use the function `IN()' in other context thought.

SELECT INTO TABLE
-----------------

   MySQL doesn't yet support `SELECT ... INTO TABLE...'. Currently
MySQL only supports `SELECT ... INTO OUTFILE...'.

Transactions
------------

   Transactions are not supported. *MySQL* will shortly support atomic
operations which are like transactions without rollback. With atomic
operations you can make a bunch of insert/select/whatever commands and
be guaranteed that no other thread will interfere. In this context you
won't usually need rollback. Currently you can do this with the help of
the `LOCK TABLES/UNLOCK TABLES' command. *Note Lock tables::

Triggers
--------

   Triggers are not supported. The planned update language will be able
to handle stored procedures, but without triggers. Triggers usually slow
down everything, even for queries when they aren't needed.

Foreign Keys
------------

   The `FOREIGN KEY' syntax in *MySQL* exists only for compatibility
with other SQL vendors `CREATE TABLE' commands: It doesn't do anything.
The `FOREIGN KEY' syntax without `ON DELETE ..' is mostly used for
documentation purposes. Some ODBC applications may uses this to produce
automatic `WHERE' clauses though, but this is usually easy to override.
`FOREIGN KEY' is sometimes used as a constraint check, but this check
is in practice unnecessary if one inserts rows in the tables in the
right order.

   In *MySQL* one can go around the problem that `ON DELETE ...' isn't
implement by adding the approative `DELETE' statement to the
application when one deletes record from a table that has `FOREIGN
KEY'.  In practice this is as quick (in some case quicker) and much
more portable than using `FOREIGN KEY'.

   Foreign keys are something that makes life very complicated, because
the foreign key definition must be stored in some database and then the
whole 'nice approach' of using only files that can be moved, copied and
removed will be destroyed.

   In the near future we will extend `FOREIGN KEYS' so that at least
the information will be saved and may be retrieved by mysqldump and
ODBC.

Some reasons NOT to use FOREIGN KEYS
....................................

   There is so many problems with the `FOREIGN KEY's that we don't know
where to start.

   * The speed impact will be terrible when `INSERTING' and `UPDATING'
     records and in this case almost all `FOREIGN KEY' checks are
     useless because one usually inserts records in the right tables in
     the right order.

   * There will also be a need to hold locks on many more tables when
     updating one because the side effects can cascade trough the hole
     database. It's MUCH faster to first delete records from one table
     and there after do delete from the other tables.

   * One can't restore a table by doing anymore by doing a full delete
     from the table and restore all records (from a new source or from
     a backup).

   * If you have foreign keys you can't dump and restore tables without
     doing this in a very specific order.

   * It's very easy to do 'allowed' circular definitions that makes the
     tables impossible to recreate with a single create statement, even
     if the definition works and is usable.

   The only nice aspect of foreign key is that it gives ODBC and some
other client programs the ability to see how a table is connected and
use this to show connection diagrams and to help building applicatons.

   *MySQL* will soon store the `FOREIGN KEY' definitions so that a
client can ask and receive an answer how the original connection was
made. The reason this can not be done is that the current `.frm' file
format does not have any place for it.

Views
-----

   MySQL doesn't support views, but this is on the TODO.

- as start of a comment
-----------------------

   Some other SQL has - as start comment. *MySQL* has # as the start
comment character, even if the *MySQL* command line tool removes all
lines that starts with -.

   MySQL will not support this degenerated comment style because we have
had many problems with automatic generated SQL queries that has used
something like the following code:

     UPDATE table_name SET credit=credit-!payment!

   Where instead of !payment! we automaticly insert the value of the
payment.

   What do you think will happen when 'payment' is negative ?

   Because 1-1 is legal in SQL, we think is terrible that '-' means
start comment.

   If you have a sql program in a textfile that contains - comments you
should use

     replace " --" " #" < text-with-funny-comments.sql | mysql database.
     
     instead of the normal
     
     mysql database < text-with-funny-comments.sql

   You can also change the - to # comments in the command file with:

     replace " --" " #" -- text-with-funny-comments.sql

   and change them back with:

     replace " #" " --" -- text-with-funny-comments.sql

What standards does *MySQL* follow?
===================================

   Entry level SQL92. ODBC level 0-2.

What functions exist only for compatibility?
============================================

   * `GRANT'. *Note Grant:: This always succeeds. You should use the
     MySQL privilege tables. *Note Privileges::

   * `CREATE INDEX'. *Note Create Index:: This always succeeds. You
     should create your index with `CREATE TABLE'. *Note Create table::
     You can also use `ALTER TABLE'. *Note Alter table::.

   * `DROP INDEX'. *Note Drop Index:: This always succeeds. You can use
     `ALTER TABLE' to drop indexes. *Note Alter table::.

Limitations of `BLOB' and `TEXT' types
======================================

   If you want to `GROUP BY' or a `ORDER BY' on a `BLOB' or `TEXT'
field, you must make the field into a fixed length object. The standard
way to do this is with the `SUBSTRING' functions. If you don't do this
only the first `max_sort_length' (default=1024) will considered when
sorting.

     SELECT comment from table order by substring(comment,20);

How to go cope without COMMIT-ROLLBACK
======================================

   MySQL doesn't support COMMIT-ROLLBACK. The problem with
COMMIT-ROLLBACK is that for it to handle this efficiently it would
require a completely different table layout than *MySQL* uses today.
*MySQL* would also need extra threads that do automatic cleanups on the
tables and the disk space needed would be much higher. This would make
*MySQL* about 2-4 times slower than it is today. One of the reasons
that *MySQL* is so much faster than almost all other SQL databases
(typical times are at least 2-3 times faster) is the lack of
COMMIT-ROLLBACK.

   For the moment, we are much more for implementing the SQL server
language (stored procedures). With this you very seldom really need
COMMIT-ROLLBACK, and you can do many more things without losing any
speed.

   Loops that need transactions can normally be coded with the help of
`LOCK TABLES' and one doesn't need cursors when one can update records
on the fly.

   We have transactions and cursors on the TODO but not quite
prioritised. If it is implemented it will be as a option to `CREATE
TABLE'. That means that COMMIT-ROLLBACK will only work on those tables
and only those tables will be slower.

   We at TcX have a greater need for a real fast database than a 100%
general database. Whenever we find a way to implement these without any
speed loss we will probably do it, but for the moment there is many more
important things to do. Check the TODO for how we prioritise things at
the moment. Customers with higher levels of support can alter this, so
things may be reprioritised.

   The current problem is actually `ROLLBACK'. Without `ROLLBACK' you
can do anything with `LOCK TABLES'. To support `ROLLBACK' *MySQL* would
had to be changed to store all old records that was updated and revert
everything back to the starting point if `ROLLBACK' was issued. For
simple cases this isn't that hard to do (the current isamlog could be
used for this), but if one wants to have `ROLLBACK' with
`ALTER/DROP/CREATE TABLE' it would make everything much harder to
implement.

   To avoid using `ROLLBACK' one can do:

  1. `LOCK TABLES ...'

  2. Test conditions.

  3. Update if everything is ok.

  4. `UNLOCK TABLES'

   This is usually much faster, but not always. The only thing this
doesn't handle if someone does a kill on the process.

   One can also use functions to update things in one operation. By
doing all updates relatively and/or only update those fields that
actually have changed one can get a very efficient application.

   For example, when we are doing updates on some customer information,
we only update the customer data that has changed and only test that not
any of the changed data, or data that depends on the changed data, has
changed in the original row. The test for change is down with the
`WHERE' clause in the `UPDATE' statement. If the record wasn't updated
we give the client a message: "Some of the data you have changed has
been changed by another user", and then we show the old row versus the
new row in a window. The user can then decide which version of the
customer record he should use.

   This gives us something like 'column locking' but actually even
better, because we only update some of the columns with relative
information. This means that a typical update statement looks something
like:

     UPDATE tablename SET pay_back=pay_back+'relative change'
     
     UPDATE customer set customer_date='current_date', address='new address',
     phone='new phone', money_he_owes_us=money_he_owes+'new_money' where
     customer_id=id and address='old address' and phone='old phone';

   As you can see, this is very efficient and even if another client has
changed the 'money_he_owes_us' or 'pay_back' amount this will still
work.

   In many cases, users have wanted `ROLLBACK' and/or `LOCK TABLES' to
manage unique identifiers for some tables. This can be handled much
more efficiently by using an `AUTO_INCREMENT' column and the *MySQL*
API function `mysql_insert_id'. *Note mysql_insert_id::

   At TcX we have never had any need for row level locking as we have
always been able to code around it. I know some cases that really need
row locking, but they are very few. If you want to have row level
locking you can do something like:

     UPDATE table_name SET row_flag=1 WHERE id=ID;

   MySQL returns `affected rows' = 1 if the row was found and row_flag
wasn't 1 in the original document. On the TODO there is `GET_LOCK' and
`RELEASE_LOCK' for those that want to implement application level
locking.

How does *MySQL* privileges work
********************************

   *MySQL* has a advanced but non-standard security/privilege system.

What can the privilege system do.
=================================

   The basic function of the *MySQL* privilege system is to give a
username on a host select,insert,update and delete privileges on a
database.

   Extra function includes the ability to have a anonymous user and give
permission to use *MySQL* specific funtions like `LOAD DATA INFILE'.

How does the privilege system work?
===================================

   In *MySQL* the combination of host and user is the unique identity.
Don't think of users, think of host+user and everything should be much
clearer.  You can for example have a user named 'Robb' at two different
hosts (with different privileges) in *MySQL* without any conflicts.

   The *MySQL* privilege system makes sure that each user may do
exactly the things that they are supposed to be allowed to do. The
system decides to grant different privileges depending on *which xuser*
connects from *which host* to *which database*.

   You can always test your privileges with the script `mysqlaccess',
which Yves Carlier has provided for the *MySQL* distribution.  *Note
Access denied::

   The following switches to `mysqld' is relevant to security:
`--skip-grant-tables'
     Do not use the privilege system att all. This gives everyone *full
     access* to all databases!

`--skip-name-resolve'
     Don't resolve hostnames. All hostnames must be IP-numbers or
     'localhost'.

`--skip-networking'
     Don't allow connections over the network (no TCP/IP).

`--secure'
     Check that the ip that was returned from `get_hostbyname' resolves
     back to the original hostname. This is done to make it harder for
     someone on the outside to get access by simulating another host.

     This is turned off by default since it sometimes takes a long time
     to check this.

   All privileges are stored in three tables. `user', `host' and `db'.

   Everything granted in the `user' table is valid for every database
that cannot be found in the `db' table. For this reason, it might be
wise to grant users (apart from superusers) privileges on a
per-database basis only.

   The `host' table is mainly there to maintain a list of "secure"
servers. At TcX `host' contains a list of all machines on the local
network. These are granted all privileges.

   The connecting user's privileges are calculated by the following
algorithm:

  1. First sort the tables by:      Table                Sorted by                                       
     host                 host without wild/hosts with wild/empty hosts   
     db                   host without wild/hosts with wild/empty hosts   
     user                 host/user                                       



     Host by putting hosts without wildcards first, followed by hosts
     with wildcards and entries with `host = ""'. Within each host sort
     by user using the same rules. Finally, in the `db' table, sort by
     db using the same rules. In the steps below, we will look through
     the sorted tables and *always use the first match found*.

  2. Get the privileges for the connecting user from the `user' table
     using the first match found. empty user.

     Call this set of privileges PRIV.

  3. Get the privileges for the connecting user from the `db' table
     using the first match found.

  4. If `host = ""' for the entry found in the `db' table, AND P with
     the privileges for the host in the `host' table, i.e.  remove all
     privileges that are not "Y" in both. (If `host <> ""', P is not
     affected. In suchcases, `host' must have matched the connecting
     host's name at least partially. Therefor it can be assumed that
     the privileges found in this row match the connecting host's
     profile.)

  5. OR (add) P with the privileges for the user from the `user' table,
     i.e. add all privileges that are "Y" in `user'.

   *Remember that if you change the tables you must do a `mysqladmin
reload' to make the changes take effect.*

   The connecting user gets the set of privileges P.

   Let's show an example of the sorting and matching! Suppose that the
user table contains this:
     +-----------+----------+-
     | Host      | User     | ...
     +-----------+----------+-
     | %         | root     | ...
     | %         | jeffrey  | ...
     | localhost | root     | ...
     | localhost |          | ...
     +-----------+----------+-

   Then the search order will be:

   * localhost/root

   * localhost/any

   * any/jeffrey

   * any/root

   So jeffrey attempting to connect on localhost will be matched by the
`localhost/any' line, not by the `any/jeffrey' line. The first match
found is used!

   So if you have access problems, print out the user table, sort it by
hand, and see where the match is being made.

   Here follows an example to add a user 'custom' that can connect from
hosts 'localhost', 'server.domain' and 'whitehouse.gov'. He wants to
have password 'stupid'. The database 'bankacount' he only want to use
from 'localhost' and the 'customer' database he wants to be able to
reach from all three hosts.

     shell> mysql mysql.
     mysql> insert into user (host,user,password)
            values('localhost','custom',password('stupid'));
     mysql> insert into user (host,user,password)
            values('server.domain','custom',password('stupid'));
     mysql> insert into user (host,user,password)
            values('whitehouse.gov','custom',password('stupid'));
     
     mysql> insert into db
            (host,db,user,Select_priv,Insert_priv,Update_priv,Delete_priv,
             Create_priv,Drop_priv)
            values
            ('localhost','bankacount','custom','Y','Y','Y','Y','Y','Y');
     mysql> insert into db
            (host,db,user,Select_priv,Insert_priv,Update_priv,Delete_priv,
             Create_priv,Drop_priv)
            values
            ('%','customers','custom','Y','Y','Y','Y','Y','Y');

   You can of course also use xmysqladmin, mysql_webadmin, mysqladmin
and even xmysql to insert/change and update values in the privilege
tables.  You can find these utilities in the Contrib directory.

The privilege tables
====================

   The grant tables privileges on rows are *select*, *insert*, *update*
and *delete*.

   The table and database privileges are *create* and *drop*.  Create
and drop are for both tables and databases. Since a user with a drop
grant can delete any table, this is the same thing as a drop grant for
the database.

   Other privileges give the right to use files (for `LOAD DATA INFILE'
and `SELECT INTO OUTFILE') and to use the administrative commands
*shutdown*, *reload*, *refresh* and *process*.

   The privilege system is based on 3 tables.

`user' table
     Contains all host+user combinations that are allowed to connect to
     the mysql server, together with their optional passwords. The
     `user' table has the following columns:      Field                Type                 Key           Default       
     Host                 char(60)             PRI           ""            
     User                 char(16)             PRI           ""            
     Password             char(16)             -             ""            
     Select_priv          enum('N','Y')        -             N             
     Insert_priv          enum('N','Y')        -             N             
     Update_priv          enum('N','Y')        -             N             
     Delete_priv          enum('N','Y')        -             N             
     Create_priv          enum('N','Y')        -             N             
     Drop_priv            enum('N','Y')        -             N             
     Reload_priv          enum('N','Y')        -             N             
     Shutdown_priv        enum('N','Y')        -             N             
     Process_priv         enum('N','Y')        -             N             
     File_priv            enum('N','Y')        -             N             



`db' table
     Contains which databases a host+user is allowed to use, and what
     he can do with the tables in each database. The `db' table has the
     following columns:      Field                       Type          Key           Default       
     Host                        char(60)      PRI           ""            
     Db                          char(32)      PRI           ""            
     User                        char(16)      PRI           ""            
     Select_priv                 enum('N','Y') -             N             
     Insert_priv                 enum('N','Y') -             N             
     Update_priv                 enum('N','Y') -             N             
     Delete_priv                 enum('N','Y') -             N             
     Create_priv                 enum('N','Y') -             N             
     Drop_priv                   enum('N','Y') -             N             



`host' table
     Is only used in big networks as a lookup for empty host entries in
     the db table.  This means that if you want a user to be able to
     use the database from all hosts in your network, you should put "
     as the host name in the db table.  In this case the `host' table
     should contain a entry for every host in your network. The `host'
     table has the following columns:      Field                       Type          Key           Default       
     Host                        char(60)      PRI           ""            
     Db                          char(32)      PRI           ""            
     Select_priv                 enum('N','Y') -             N             
     Insert_priv                 enum('N','Y') -             N             
     Update_priv                 enum('N','Y') -             N             
     Delete_priv                 enum('N','Y') -             N             
     Create_priv                 enum('N','Y') -             N             
     Drop_priv                   enum('N','Y') -             N             



   * The HOST and DB columns may contain a string with the SQL
     wildcards `%' and `_'. Leaving any of these columns empty is
     equivalent to setting it to '%'.

   * A HOST may be `localhost', a hostname, an IP number or a string
     with wildcards. An empty host in the db table means any host in
     the host table.  An empty host in the host or user table means *any
     host that can create a TCP connection to your server*.

   * A DB is the name of a database or an SQL regexp.

   * An empty USER column means any username will do. One can't have
     wildcards in the user name.

   * A user not matching anything in the `user' table will be processed
     as a no-name user.

   * The privileges from the user table are OR'ed to the `db' table.
     This means that a superuser only needs to be in the user table
     with all privilege-flags set to `Y'.

   You can use a entry like `123.444.444.%' in the host table to give
every user on a IP C-net access. To avoid the possiblity that somebody
tries to fool this setup by nameing a host to
`123.444.444.somewhere.com' to fool the permission system. To avoid
this problem *MySQL* disallows all hostnames that start with digits and
a dot. So if your host is named something like `1.2.foo.com' it will
never be allowed with name matching. Use the IP number in this case.

Adding new user privileges to *MySQL*
=====================================

   To add privileges to the *MySQL* database:

   This assumes the current user has insert privileges for the mysql db
table and reload privileges. The server (mysqld) has to be running. If
it is not, start it with `safe_mysqld --log &'.

     > mysql mysql
       insert into user values ('%','monty',password('something'),'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y') ;
       insert into user (host,user,password) values('localhost','dummy','') ;
       insert into user values ('%','admin','','N','N','N','N','N','N','Y','N','Y','Y') ;
       quit
     > mysqladmin reload

   This makes three new users:
`Monty'
     Full superuser, but must use password when using *MySQL*.

`admin'
     Doesn't need a password but is only allowed to use `mysqladmin
     reload', `mysqladmin refresh' and `mysqladmin processlist'. May be
     granted individual database privileges through table `db'.

`dummy'
     Must be granted individual database privileges through table `db'.

Default privileges.
===================

   The default privileges (set in `scripts/mysql_install_db') let root
do anything. Any user can do anything with any database whose name is
'test' or starts with 'test_'. A normal user can't use `mysqladmin
shutdown' or `mysqladmin processlist'. See the script
(`scripts/mysql_install_db') for an example on how to add other users.

   The privilege tables are read into mysqld with `mysqladmin reload'.

A example of permission setup.
==============================

   A common mistake is to forget that passwords are stored encrypted,
which leads to something like:

   `INSERT INTO user VALUES
('%','jeffrey','bLa81m0','Y','Y','Y','N','N','N','N','N', 'N','N');'

   Then (of course) a `mysqladmin reload' to make the authentication
change take effect, then trying to connect to the server:

   $ ` ./mysql -h sqlserver -u jeffrey -p bLa81m0 test' Access denied

   Try this instead:

   `INSERT INTO user VALUES
('%','jeffrey',password('bLa81m0'),'Y','Y','Y','N','N','N','N','N','N','N');'

   And like before `mysqladmin reload' to make the authentication change
take effect.

   Now things should work.

Why do I get this `Access denied?' error.
=========================================

   * Have you installed the *MySQL* grant tables with the script
     'mysql_install_db'? Test by executing 'mysql -u root test'. This
     should not give an error. You can also check if you have a file
     'user.ISD' in the mysql database directory (ordinary
     install_dir/var/mysql/user.ISD).

   * Remember that you have to do 'mysqladmin reload' each time you
     change the grant tables. Otherwise the old tables are still used!

   * For testing, you should start the mysqld demon with the
     `--without-grant-tables' option. Now you can change the *MySQL*
     grant tables and use the script `mysqlaccess' to check if your
     grants works. `mysqladmin reload' tells the mysqld demon to start
     using the new grant tables.

   * Even if you have access problems with perl, python, or ODBC,
     always test your privilege problems with `mysql -u user database'
     or `mysql -uuser -ppassword database'.

   * If you get the error 'Access denied' when trying to connect to the
     database with `mysql -u user database' then you have a problem with
     the 'user' table. Check this by doing `mysql -u root mysql' and
     `select * from user'. You should get an entry with 'hostname' and
     'user' matching your computers hostname and your username. If the
     client and the server is running on the same host and you haven't
     used the `--host' option to mysql and you are not using MIT
     threads, 'localhost' is a synonym for your hostname.

   * The `Access denied' error message will tell you who you are trying
     to log in as, from which host you are trying to log in from and if
     you was using a password or not. You should normally have one
     entry in the `user' table that exactly matches your host and user,
     exactly as given in the error message.

   * If `mysql -u root test' works but `mysql -h your_hostname -u root
     test' gives 'Access denied' then you don't have the right name for
     your host in the user table. For example if you have an entry with
     host 'tcx' in the 'user' table, but your DNS tells *MySQL* that
     your hostname is 'tcx.subnet.se' then the entry will not work.
     Test by adding a record with the IP of your host in the 'user'
     table. You can, natuarally, also add a host with a wildcard (for
     example 'tcx%') in the 'user table' (but using hostnames ending
     with % is pretty insecure).

   * When using MIT threads, localhost is never used. All connections
     to the mysqld demon is done by TCP IP and you must have your real
     hostname in 'user' even if you are running the client on the same
     host as the server.

   * If you get the error 'Access to database denied' then you have a
     problem with the db table. If the used entry in the db table has
     an empty hostname, check also the corresponding entry in the
     'host' table.

   * If `mysql -u user database' works on the server machine, but
     `mysql -u host -u user database' doesn't work on another client
     machine, then you don't have the client machine in the 'user' or
     the 'db' table.

   * If you can't get password to work, remember that passwords must be
     inserted with the PASSWORD function. *Note Security example::

   * If `mysql -u user test' works but `mysql -u user other_database'
     doesn't work, you don't have the other_database in the 'db' table.

   * If you get 'Access to database denied' when using the `SELECT ...
     INTO OUTFILE' or `LOAD DATA' SQL commands then you probably don't
     have the file_priv privilege set for you in the user table.

   * If everything else fails, start the `mysqld' demon with:
     `--debug=d,general,query'. This will print info about the host and
     user that tries to connect and also information about each command
     issued. *Note Debugging::.

   * If you have any other problems with the *MySQL* grant tables and
     feel you must post the problem to the list, always add a dump of
     the *MySQL* grant tables. You can dump the tables with the
     `mysqldump mysql' command. And as always post your problem with the
     `mysqlbug' script.

*MySQL* language reference
**************************

Literals. How do you write strings and numbers?
===============================================

Strings
-------

   A string may have ' or " around it.

   \ is a escape character. The following escape characters are
recognised:
`\0'
     A ascii 0 character.

`\n'
     A newline character.

`\t'
     A tab character.

`\r'
     A return character.

`\b'
     A backspace character.

`\''
     A `'' character.

`\"'
     A `"' character.

`\\'
     A `\' character.

`\%'
     A `%' character. This is used in wild-card strings to search after
     `%'.

`\_'
     A `_' character. This is used in wild-card strings to search after
     `_'.

     A ' inside a string started with ' may be written as ''.
     A " inside a string started with " may be written as "".

   Some example selects that shows how it works.
     MySQL> select 'hello', "'hello'", '""hello""', '''h''e''l''l''o''', "hel""lo";
     1 rows in set (0.00 sec)
     
     +-------+---------+-----------+-------------+--------+
     | hello | 'hello' | ""hello"" | 'h'e'l'l'o' | hel"lo |
     +-------+---------+-----------+-------------+--------+
     | hello | 'hello' | ""hello"" | 'h'e'l'l'o' | hel"lo |
     +-------+---------+-----------+-------------+--------+

     mysql> select 'hello', "hello", '""hello""', "'ello", 'e''l''lo', '\'hello';
     1 rows in set (0.00 sec)
     
     +-------+-------+-----------+-------+--------+--------+
     | hello | hello | ""hello"" | 'ello | e'l'lo | 'hello |
     +-------+-------+-----------+-------+--------+--------+
     | hello | hello | ""hello"" | 'ello | e'l'lo | 'hello |
     +-------+-------+-----------+-------+--------+--------+

     mysql> select "This\nIs\nFour\nlines";
     1 rows in set (0.00 sec)
     
     +--------------------+
     | This
     Is
     Four
     lines |
     +--------------------+
     | This
     Is
     Four
     lines |
     +--------------------+

   If you want to insert binary data into a blob the following
characters must be represented by escape sequences:
`\0'
     Ascii 0. Should be replaced with "\0" (A backslash and a 0 digit).

`\'
     Ascii 92, backslash

`''
     Ascii 39, Single quote

`"'
     Ascii 33, Double quote

Numbers
-------

   Integers are just a sequence of digits. Floats use `.' as a decimal
separator.

   Examples of valid numbers are: `1221', `294.42', `-32032.6809e+10'.

`NULL'
------

   When using the text file export formats, `NULL' may be represented
by `\N'. *Note Load::

Database, table, index and column names
---------------------------------------

   Database, table, index and column names all follow the same rules in
*MySQL*.

   A name may use alphanumeric characters from the default character
set. This is by default ISO-8859-1 Latin1 but may be changed when
compiling *MySQL*.

   Since *MySQL* needs to be able to decide if something is a name or a
number the following special cases occurs.

   * A name can not consist of only numbers.

   * A difference from many other systems is that it may start with a
     number.

   * It is not recommended to use names like `1e'. This is because
     expressions like `1e+1' may be interpreted like the expression `1e
     + 1' or the number `1e+1'.

   So punctuation characters like `.' and `@' are not allowed since
they will be used to extend *MySQL*.

Column types.
=============

   The following column types are supported:

   * M means Max display size.

   * L means the actual length in a single row.

   * M means the maximum length.

   * D means the number of decimals.

Name                          Description                            Size  
TINYINT[(D)] [UNSIGNED]        A very small integer. Signed range    1     
[ZEROFILL]                    -128 - 127. Unsigned range 0 - 255.          
SMALLINT[(D)]. [UNSIGNED]      A small integer. Signed range -32768  2     
[ZEROFILL]                    - 32767. Unsigned range 0 - 65535.           
MEDIUMINT[(D)] [UNSIGNED]      A medium integer. Signed range        3     
[ZEROFILL]                    -8388608-8388607. Unsigned range 0 -         
                              16777215.                                    
INT[(D)] [UNSIGNED]            A normal integer. Signed range        4     
[ZEROFILL]                    -2147483648 - 2147483647. Unsigned           
                              range 0 - 4294967295.                        
BIGINT[(D)] [UNSIGNED]         A large integer. Signed range         8     
[ZEROFILL]                    -9223372036854775808 -                       
                              9223372036854775807. Unsigned Range 0        
                              - 18446744073709551615.                      
FLOAT(Precision)               A small floating point number.        4     
                              Precision can be 4 or 8. FLOAT(4) is a       
                              single precision number and FLOAT(8)         
                              is a double precision number (se the         
                              DOUBLE entry). This syntax is for            
                              ODBC compatibility. Range                    
                              -3.402823466E+38F - -1.175494351E-38,        
                              0, -1.175494351E-38 -                        
                              3.402823466E+38F.                            
FLOAT[(M,D)]                   A small floating point number.        4     
                              Cannot be unsigned. Range                    
                              -3.402823466E+38F - -1.175494351E-38,        
                              0, -1.175494351E-38 -                        
                              3.402823466E+38F.                            
DOUBLE PRECISION[(M,D)]        A normal floating point number.       8     
                              Cannot be unsigned. Range                    
                              -1.7976931348623157E+308 -                   
                              -2.2250738585072014E-308, 0,                 
                              2.2250738585072014E-308 -                    
                              1.7976931348623157E+308.                     
REAL[(M,D)]                   Same as DOUBLE                         8     
DECIMAL [(M,D)]                An unpacked floating point number.    M+D   
                              Cannot be unsigned. Currently the            
                              same range maximum range as a double.        
                              Behaves as a CHAR column                     
NUMERIC [(M,D)]                Same as DECIMAL                       M+D   
TIMESTAMP [(M)]                An automatic timestamp.               4     
DATE                           A type to store date information.     4     
                              Uses the "YYYY-MM-DD" syntax, but may        
                              be updated with a number or a string.        
                              Understands at least the following           
                              syntaxes: 'YY-MM-DD', 'YYYY-MM-DD',          
                              'YYMMDD', 'YYMM', 'YY'.  Range               
                              0000-00-00 to 9999-12-31.                    
TIME                           A type to store time information.     3     
                              Uses the "HH:MM:SS" syntax, but may be       
                              updated with a number or a string.           
                              Understands at least the following           
                              syntaxes: 'HH:MM:DD, 'HHMMDD',               
                              'HHMM', 'HH'.                                
DATETIME                       A type to store date and time         8     
                              information. Format "YYYY-MM-DD              
                              HH:MM:SS". Takes 8 bytes. Range              
                              '0000-01-01 00:00:00' - '9999-12-31          
                              23:59:59'.                                   
CHAR(M) [binary]               A fixed length string that is always  M     
                              filled up with spaces to the                 
                              specified length. Range 1 - 255              
                              characters. All end space are removed        
                              when retrieved. Is sorted and                
                              compared case insensitively unless the       
                              binary keyword is given.                     
VARCHAR(M) [binary]            A variable length string that is      L+1   
                              stored with its length. Maximum range        
                              1 - 255 characters. Is sorted and            
                              compared case insensitively unless the       
                              binary keyword is given.                     
TINYTEXT and TINYBLOB          A `TEXT'/`BLOB' with max length of    L+1   
                              255 characters.                              
TEXT and BLOB                  A `TEXT'/`BLOB' with max length of    L+2   
                              65535 characters.                            
MEDIUMTEXT and MEDIUMBLOB      A `TEXT'/`BLOB' with max length of     L+3  
                              16777216 characters.                         
LONGTEXT and LONGBLOB          A `TEXT'/`BLOB' with max length of     L+4  
                              4294967295 characters.                       
ENUM('value','value2',...)     A string object that can have only    1 or  
                              one set of allowed values. *Note Type  2     
                              details::.                                   
SET('value','value2',...)      A string object that can have one or  1-8   
                              many values of a set of allowed              
                              values. *Note Type details::.                

More about data types
---------------------

Database size info.
...................

   In the above table L means the actual length of a instance and M the
maximum length. So L+1 for "abcd" means 5 bytes in the database.

   If you use any data type with a L in the length field you will get a
variable length record format.

The numeric types
.................

   All integer types can have a optional argument `unsigned'.  This can
be used when you only want to allow positive numbers in the column or
you need a little bigger numerical range for the column.

   Also for all integer columns the optional argument `ZEROFILL' means
that the column will be padded with zeroes up to the maximum length.

   Max display size and decimals are for formatting and calculation of
max column width.

   When storing a value in a integer that is outside its range, *MySQL*
stores the maximum (or minimum) possible value. When doing an `ALTER
TABLE' or `LOAD DATA INFILE' one gets these conversions as 'warnings'.
We have on the TODO to make INSERT and UPDATE also can return warnings,
but this is scheduled for the next protocol change.

   For example when storing `-999999999999999' into a int column the
value end up as `-2147483648'. And `9999999999999999' end up as
`2147483647'.

   And if the int is unsigned the stored values above becomes `0' and
`4294967296'.

   The same rules goes for all other integer types.

   When returning data for an int(4) column that does not fit in it
*MySQL* will return 9.99. And is an `UPDATE' a warning will be issued.

   Note that a type like `decimal(4,2)' means maximum 4 characters with
two decimal points. That gives a range between `-.99' -> `9.99'.

   To avoid some rounding problems, *MySQL* always rounds everything
that it stores in any floating point column according to the number of
decimals. This means that `2.333' stored into `float(8,2)' is stored as
`2.33'.

`TIMESTAMP' type
................

   Has a range of 1 Dec 1970 time 0.00 to sometime in the year 2106 and
a resolution of one second. Will be automatically updated if not used
in a statement that updates a row or if set to `NULL'. Can be a (part
of) a index. Note that if you have many timestamp columns in a row, then
only the first timestamp column will be automatically updated. Any
timestamp column will be set to the current time if set to `NULL'.
Depending on the display size one gets one of the following formats:
"YYYY-MM-DD HH:MM:SS", "YY-MM-DD HH:MM:SS", "YYYY-MM-DD" or "YY-MM-DD".

`TEXT' and `BLOB' types
.......................

   These are objects that can have a variable length without upper
limit.  All TEXT and BLOB objects are stored with is length (saved in 1
to 4 bytes depending on the type of object). The maximum `TEXT' and
`BLOB' length you can use is dependent on available memory and client
buffers. The only differences between `TEXT' and `BLOB' is that `TEXT'
is sorted and compared case insensitively while `BLOB' is compared case
insensitive (by character values). `TEXT' and `BLOB' objects CANNOT be
index.

   A BLOB is a binary large object which can hold any amount of data.
There are 4 kinds of blobs *Note Column types::. Normally one can regard
a BLOB as a VARCHAR without a specified limit.

   `TEXT' is a `BLOB' that is sorted and compared case insensitively.

   A `BLOB'/`TEXT' column may not be bigger that the message buffer.
Note that you have to change the message buffer on both the server and
the client. *Note MySQL parameters::.

   `MyODBC' defines `BLOB's as `LONGVARBINARY' and `TEXT's as
`LONGVARCHAR'.

   Restrictions for `BLOB' and `TEXT' columns:

  1. A `BLOB' or `TEXT' cannot be a index or a part of a index

  2. When one sorts or groups a `BLOB' or `TEXT' only the first
     `max_sort_length' (default 1024) of the blob is used. This value
     can be changed by the `-O' option when starting the mysqld demon.
     One can group on an expression involving a `BLOB'/ `TEXT': `SELECT
     id,SUBSTR(blob,1,100) GROUP BY 2'

  3. There is no end space truncation for `BLOB' and `TEXT' as there is
     for `CHAR' and `VARCHAR'.

`ENUM' type
...........

   A string object that can have only one set of allowed values. The
value to be stored may be given case independently. If one tries to
store a non-existing value, "" is stored. If used in a number context
this object returns/stores the value index. If there is less than 255
possible values this object occupies 1 byte, else two bytes (with a
maximum of 65535 different values). Note that if a integer is put in the
`ENUM' you get the corresponding string with the first counting as
number zero. Sorting on `ENUM' types is done after the order of the
strings in the enum.

   For example the column `test ENUM("one","two", "three")' can have
any off these values:

     "one"
     "two"
     "three"

`SET' type
..........

   A string object that can have one or many values of a set of allowed
values. Each value is separated by a ','. If used in a number context
this object returns/stores the bit positions of the used values. This
object occupies (number_of_different_values-1)/8+1 bytes, rounded up to
1,2,3,4 or 8. One can't have more than 64 different values. Note that if
a integer is put in the `SET' you get the corresponding string with the
first bit corresponding to the first string. Sorting on `SET' types is
done numerically.

   For example the column `test SET("one","two")' can have any off
these values:

     ""
     "one"
     "two"
     "one,two"

Choosing the right type for a column.
-------------------------------------

   Try to use the most precise type in all cases. For example for a
integer between 1-99999 a `unsigned mediumint' is the best type.

   A common problem is representing monetary values accurately. In
*MySQL* you should use the `DECIMAL' type. This is stored as a string
so no loss of accuracy should occur. If accuracy is not to important
the `DOUBLE' type may also be good enough.

   To get real high precision you can always convert to a fixed point
type stored in a `BITINT'. This allows you to do all calculation with
integers and only convert the result back to floating point.

Column indexes
--------------

   You can have indexes on all *MySQL* columns except `BLOB' and `TEXT'
types. Using indexes on the relevant columns is the most important
thing in getting your selects to run fast.

   For `CHAR' and `VARCHAR' columns you can have a index on a prefix.
The example below show how to create a index for the first 10
characters of a column. This is much faster and requires less disk space
than having a index on the whole column.

     CREATE TABLE test (
     name CHAR(200),
     KEY name (last_name(10));

Multiple column indexes
-----------------------

   *MySQL* can have one index on parts of different columns.

   A multiple column index can be considered as a sorted array where the
columns are concatenated.  This makes for fast queries where the first
column in the index is a known quantity and the other columns are not.

   Suppose that you have a table:

     CREATE TABLE test (
     id INT,
     last_name CHAR(30),
     first_name CHAR(30),
     PRIMARY KEY (id),
     INDEX name (last_name,first_name));

   Then the index `name' is a index over last_name and first_name.

   The `name' index will be used in the following queries:

     SELECT * FROM test WHERE last_name="Widenius";
     
     SELECT * FROM test WHERE last_name="Widenius" AND first_name="Michael";
     
     SELECT * FROM test WHERE last_name="Widenius" AND
                              (first_name="Michael" OR first_name="Monty");
     
     SELECT * FROM test WHERE last_name="Widenius" and
                              first_name >="M" and first_name < "N";

   The `name' index will NOT be used in the following queries:

     SELECT * FROM test WHERE first_name="Michael";
     
     SELECT * FROM test WHERE last_name="Widenius" or first_name="Michael";

Type mapping to ease moving table definitions between different databases engines
---------------------------------------------------------------------------------

   To support easier use of code from different SQL vendors, *MySQL*
does supports the following mappings:

binary(num)                          char(num) binary                     
char varying                         varchar                              
float4                               float                                
float8                               double                               
int1                                 tinyint                              
int2                                 smallint                             
int3                                 mediumint                            
int4                                 int                                  
int8                                 bigint                               
long varbinary                       blob                                 
long varchar                         text                                 
middleint                            mediumint                            
varbinary(num)                       varchar(num) binary                  

Functions for use in `SELECT' and `WHERE' clauses
=================================================

   A `select_expression' or `where_definition' can consist of any
expression using the following functions:

   In the examples below the output of the `mysql' program has been
shortended. So

     mysql> select mod(29,9);
     1 rows in set (0.00 sec)
     
     +-----------+
     | mod(29,9) |
     +-----------+
     |         2 |
     +-----------+

   Has been converted to

     mysql> select mod(29,9);                ->      2

Grouping functions.
-------------------

`('
`)'
     Parenthesis. Force order of evaluation in a expression.
          mysql> select 1+2*3;                     ->      7
          mysql> select (1+2)*3;                   ->      9

Normal arithmetic operations.
-----------------------------

`+'
     Addition

`-'
     Subtraction.

`*'
     Multiplication

`/'
     Division. A division by zero results in a `NULL'.
          mysql> select 102/(1-1);                 ->      NULL

Bit functions.
--------------

   These have a range of maximum 64 bits because *MySQL* uses bigint
(64 bit) arithmetic.
`|'
     Bitwise OR.
          mysql> select 29 | 15;                   ->     31

`&'
     Bitwise and.
          mysql> select 29 & 15;                   ->      13

`BIT_COUNT()'
     Number of set bits in an argument.
          mysql> select bit_count(29);             ->      4

Logical operations.
-------------------

   All logical function return 1 (TRUE) or 0 (FALSE).
`NOT'
`!'
     Logical NOT. Return 1 if argument is 0 else return 0.
          mysql> select NOT 1;                    ->      0
          mysql> select NOT NULL;                 ->      NULL
          mysql> select ! (1+1);                  ->      0
          mysql> select ! 1+1;                    ->      1

`OR'
`||'
     Logical OR. Return 1 if any of the arguments are differs from 0.
          mysql> select 1 || 0;                   ->      1
          mysql> select 0 || 0;                   ->      0
          mysql> select 1 || NULL;                ->      1

`AND'
`&&'
     Logical AND. Return 1 if all of the arguments is differs from 0.
          mysql> select 1 && NULL;                ->      0
          mysql> select 1 && 0;                   ->      0

Comparison operators.
---------------------

   Returns 1 (TRUE) or 0 (FALSE). These functions work for both numbers
and strings. *MySQL* uses the following rules to decide how the compare
is done:
   * If both arguments to a compare operation are strings, compare as
     strings.

   * If both arguments are integers, compare as integers.

   * If one of arguments are a `TIMESTAMP' or `DATETIME' column and the
     other argument is a constant. In this case the constant is
     converted to a timestamp before the comparasion. All this is to be
     more ODBC friendly.

   * In all other case compare as floating point numbers (real).

`='
     Equal.
          mysql> select 1 = 0;                    ->      0
          mysql> select "0" = 0;                  ->      1
          mysql> select "0.0" = 0;                ->      1
          mysql> select "0.01" = 0;               ->      0
          mysql> select ".01" = 0.01;             ->      1

`<>'
`!='
     Not equal.
          mysql> select ".01" <> "0.01";          ->      1
          mysql> select .01 <> "0.01";            ->      0
          mysql> select "zapp" <> "zappp";        ->      1

`<='
     Smaller than or equal.
          mysql> select 0.1 <= 2;                 ->      1

`<'
     Smaller than.
          mysql> select 2 <= 2;                   ->      1

`>='
     Bigger than or equal.
          mysql> select 2 >= 2;                   ->      1

`>'
     Bigger than.
          mysql> select 2 > 2;                    ->      0

`ISNULL(A)'
     Returns 1 if `A' is `NULL' else 0. Same as `(A = NULL)'.
          mysql> select isnull(1+1);              ->      0
          mysql> select isnull(1/0);              ->      1

`A BETWEEN B AND C'
     `A' is bigger or equal as `B' and `A' is smaller or equal to `C'.
     Does the same thing as `(A >= B AND A <= C)' if the all arguments
     are of the same type.  It's the first argument (`A') that decides
     how the comparison should be done!  If `A' is a string expression,
     compare as strings. If `A' is a integer expression compare as
     integers, else compare as reals.
          mysql> select 1 between 2 and 3;        ->      0
          mysql> select 2 between 2 and 3;        ->      1
          mysql> select 2 between 2 and "3";      ->      1
          mysql> select 2 between 2 and "x-3";    ->      0

String comparison functions.
----------------------------

`expr IN (value,...)'
     Returns 1 if expr is any of the values in the `IN' list, else it
     returns 0.  If all values are constants, then all values are
     evaluated according to the type of expr and sorted. The search for
     them item is then done by using a binary search. This means `IN'
     is very quick when used with constants in the `IN' part.
          mysql> select 2 in (0,3,5,"wefwf");               ->      0
          mysql> select "wefwf" in (0,3,5,"wefwf");         ->      1

`expr NOT IN (value,...)'
     Same as `NOT (expr IN (value,...))'

`expr LIKE expr'
     SQL simple regular expression comparison. Returns 1 (TRUE) or 0
     (FALSE).  With `LIKE' you have two wild characters.

     `%'           Matches any number of characters, even   
                   zero characters.                         
     `_'           Matches exactly one character.           
     `\%'          Matches one `%'.                         
     `\_'          Matches one `_'.                         

          mysql> select "David!" like "David_";             ->      1
          mysql> select "David!" like "David\_";            ->      0
          mysql> select "David_" like "David\_";            ->      1
          mysql> select "David!" like "%D%v%";              ->      1

`expr NOT LIKE expr'
     Same as `NOT (expr LIKE expr)'.

`expr REGEXP expr'
     Checks string against extended regular expr. *Note Regexp::.
          mysql> select "Monty!" regexp "m%y%%";            ->      0
          mysql> select "Monty!" regexp ".*";               ->      1

`expr NOT REGEXP expr'
     Same as `NOT (expr REGEXP expr)'.

`STRCMP()'
     Returns 0 if the strings are the same. Otherwise return -1 if first
     argument is smaller according to the current sort-order, otherwise
     it returns 1.
          mysql> select strcmp("text", "text2");            -> -1
          mysql> select strcmp("text2", "text");            -> 1
          mysql> select strcmp("text", "text");             -> 0

Control flow functions.
-----------------------

`IFNULL(A,B)'
     If `A' is not `NULL' it returns `A', else `B'.
          mysql> select ifnull(1,0);        -> 1
          mysql> select ifnull(0,10);       -> 0
          mysql> select ifnull(1/0,10);     -> 10

`IF(A,B,C)'
     If `A' is true (`A <> 0' and `A <> NULL') then return `B', else
     return `C'.
          mysql> select if(1>2,2,3);        -> 3

Mathematical functions.
-----------------------

   All mathematical functions returns `NULL' in the case of a error.
`-'
     Sign. Changes sign of argument.
          mysql> select - 2;                -> -2

`ABS()'
     Absolute value.
          mysql> select abs(2);             -> 2
          mysql> select abs(-32);           -> 32

`SIGN()'
     Sign of argument. Returns -1, 0 or 1.
          mysql> select sign(-32);          -> -1
          mysql> select sign(0);            -> 0
          mysql> select sign(234);          -> 1

`MOD()'
`%'
     Module (like % in C).
          mysql> select mod(234, 10);       -> 4
          mysql> select 253 % 7;            -> 1
          mysql> select mod(29,9);                -> 2

`FLOOR()'
     Largest integer value not greater than x.
          mysql> select floor(1.23);              -> 1
          mysql> select floor(-1.23);             -> -2

`CEILING()'
     Largest integer value not greater than x.
          mysql> select ceiling(-1.23);           -> -1
          mysql> select ceiling(1.23);            -> 2

`ROUND(N)'
     Round argument `N' to a integer.
          mysql> select round(-1.23);             -> -1
          mysql> select round(-1.58);             -> -2
          mysql> select round(1.58);              -> 2

`ROUND(Number,Decimals)'
     Round argument `Number' to a number with `Decimals' decimals.
          mysql> select ROUND(1.298, 1);          -> 1.3

`EXP(N)'
     Returns the value of `e' (the base of natural logarithms) raised to
     the power of `N'.
          mysql> select exp(2);                   -> 7.389056
          mysql> select exp(-2);                  -> 0.135335

`LOG(X)'
     Return the natural logarithm of `X'.
          mysql> select log(2);             -> 0.693147
          mysql> select log(-2);            -> NULL

`LOG10(X)'
     return the base-10 logarithm of `X'.
          mysql> select log10(2);           -> 0.301030
          mysql> select log10(100);                 -> 2.000000
          mysql> select log10(-100);                -> NULL

`POW(X,Y)'
`POWER(X,Y)'
     Return the value of `X' raised to the power of `Y'.
          mysql> select pow(2,2);           -> 4.000000
          mysql> select pow(2,-2);                  -> 0.250000

`sqrt(X)'
     Returns the non-negative square root of `X'.
          mysql> select sqrt(4);            -> 2.000000
          mysql> select sqrt(20);           -> 4.472136

`PI()'
     Return the value of PI.
          mysql> select PI();               -> 3.141593

`COS(X)'
     Return the cosine of `X', where `X' is given in radians.
          mysql> select cos(PI());                  -> -1.000000

`SIN(X)'
     Return the sine of `X', where `X' is given in radians.
          mysql> select sin(PI());                  -> 0.000000

`TAN(X)'
     Returns the tangent of `X', where `X' is given in radians.
          mysql> select tan(PI()+1);                -> 1.557408

`ACOS(X)'
     Return the arc cosine of `X'; that is the value whose cosine is
     `X'. If `X' is not in the range -1 to 1 `NULL' is returned.
          mysql> select ACOS(1);                  -> 0.000000
          mysql> select ACOS(1.0001);             -> NULL
          mysql> select ACOS(0);          -> 1.570796

`ASIN(X)'
     Return the arc sine of `X'; that is the value whose sine is `X'.
     If `X' is not in the range -1 to 1 `NULL' is returned.
          mysql> select ASIN("0.2");              -> 0.201358
          mysql> select ASIN("foo");              -> 0.000000

`ATAN(X)'
     Return the arc tangent of `X'; that is the value whose tangent is
     `X'.
          mysql> select ATAN(2);          -> 1.107149
          mysql> select ATAN(-2);         -> -1.107149

`ATAN2(X,Y)'
     Return the arc tangent of the two variables `X' and `Y'. It is
     similar to calculating the arc tangent of `Y / X', except that the
     signs of both arguments are used to determine the quadrant of the
     result.
          mysql> select ATAN(-2,2);               -> -0.785398
          mysql> select ATAN(PI(),0);             -> 1.570796

`COT(N)'
     Return the cotangens of `N'.
          mysql> select COT(12);          -> -1.57267341
          mysql> select COT(0);           -> NULL

`RAND([X])'
     Returns a random float, `0 <= x <= 1.0', using the integer
     expression `X' as the optional seed value.
          mysql> SELECT RAND();           -> 0.5925
          mysql> SELECT RAND(20);         -> 0.1811
          mysql> SELECT RAND(20);         -> 0.1811
          mysql> SELECT RAND();           -> 0.2079
          mysql> SELECT RAND();           -> 0.7888

`MIN(X,Y...)'
     Min value of arguments. Must have 2 or more arguments, else these
     are `GROUP BY' functions. The arguments are compared as numbers.
     If no records are found `NULL' is returned.
          mysql> SELECT MIN(2,0);                         -> 0
          mysql> SELECT MIN(34,3,5,767);                  -> 3
          mysql> SELECT MIN(a) from table where 1=0;      -> NULL

`MAX(X,Y...)'
     Max value of arguments. Must have 2 or more arguments, else these
     are `GROUP BY' functions. The arguments are compared as numbers.
     If no records are found `NULL' is returned.
          mysql> SELECT MAX(34,3,5,767);                  -> 767
          mysql> SELECT MAX(2,0,4,5,34);                  -> 34
          mysql> SELECT MAX(a) from table where 1=0;      -> NULL

`DEGREES(N)'
     Return `N' converted from radians to degrees.
          mysql> select DEGREES(PI());                    -> 180.000000

`RADIANS(N)'
     Return `N' converted from degrees to radians.
          mysql> select RADIANS(90);                      -> 1.570796

`TRUNCATE(Number, Decimals)'
     Truncate number `Number' to `Decimals' decimals.
          mysql> select TRUNCATE(1.223,1);                -> 1.2
          mysql> select TRUNCATE(1.999,1);                -> 1.9
          mysql> select TRUNCATE(1.999,0);                -> 1

String functions.
-----------------

`ASCII(S)'
     Returns the ASCII code value of the leftmost character of `S'. If
     `S' is `NULL' return `NULL'.
          mysql> SELECT ascii(2);                         -> 50
          mysql> SELECT ascii("dx");                      -> 100

`CHAR(X,...)'
     Returns a string that consist of the characters given by the ASCII
     code values of the arguments. `NULLs' are skipped.
          mysql> SELECT char(77,121,83,81,"76");          -> "MySQL"

`CONCAT(X,Y...)'
     Concatenates strings. May have more than 2 arguments.
          mysql> SELECT CONCAT("My", "S", "QL");          -> "MySQL"

`LENGTH(S)'
`OCTET_LENGTH(S)'
`CHAR_LENGTH(S)'
`CHARACTER_LENGTH(S)'
     Length of string.
          mysql> SELECT length("text");                   -> 4
          mysql> SELECT octet_length("text");             -> 4

`LOCATE(A,B)'
`POSITION(B IN A)'
     Returns position of `A' substring in `B'. The first position is 1.
     Returns 0 if `A' is not in `B'.
          mysql> select locate("bar", "foobarbar");         -> 4
          mysql> select locate("xbar", "foobar");           -> 0

`INSTR(A,B)'
     Returns position of first substring `B' in string `A'. This is the
     same as `LOCATE' with swapped parameters.
          mysql> select instr("foobarbar", "bar");         -> 4
          mysql> select instr("xbar", "foobar");           -> 0

`LOCATE(A,B,C)'
     Returns position of first substring `A' in string `B' starting at
     `C'.
          mysql> select locate("bar", "foobarbar",5);        -> 7

`LEFT(str,length)'
     Gets length characters from beginning of string.
          mysql> select left("foobarbar", 5);             -> "fooba"

`RIGHT(A,B)'
`SUBSTRING(A FROM B)'
     Gets `B' characters from end of string `A'.
          mysql> select right("foobarbar", 5);            -> "arbar"
          mysql> select substring("foobarbar" from 5);    -> "arbar"

`LTRIM(str)'
     Removes space characters from the beginning of string.
          mysql> select ltrim("  barbar");                -> "barbar"

`RTRIM(str)'
     Removes space characters from the end of string.  mysql> select
     rtrim("barbar   ");             -> "barbar"

`TRIM([[ BOTH | LEADING | TRAILING] [ A ] FROM ] B)'
     Returns a character string with all `A' prefixes and/or suffixes
     removed from `B'. If `BOTH', `LEADING' and `TRAILING' isn't used
     `BOTH' are assumed. If `A' is not given, then spaces are removed.
          mysql> select trim("  bar   ");                      -> "bar"
          mysql> select trim(leading "x" from "xxxbarxxx");    -> "barxxx"
          mysql> select trim(both "x" from "xxxbarxxx");       -> "bar"
          mysql> select trim(trailing "xyz" from "barxxyz");   -> "barx"

`SOUNDEX(S)'
     Gets a soundex string from `S'. Two strings that sound 'about the
     same' should have identical soundex strings. A 'standard' soundex
     string is 4 characters long, but this function returns an
     arbitrary long string. One can use `SUBSTRING' on the result to
     get a 'standard' soundex string.  All non alpha characters are
     ignored in the given string. All characters outside the A-Z range
     are treated as vocals.
          mysql> select soundex("Hello");                 -> "H400"
          mysql> select soundex("Bдttre");                -> "B360"
          mysql> select soundex("Quadratically");         -> "Q36324"

`SUBSTRING(A, B, C)'
`SUBSTRING(A FROM B FOR C)'
`MID(A, B, C)'
     Returns substring from `A' starting at `B' with `C' chars. The
     variant with `FROM' is ANSI SQL 92 syntax.
          mysql> select substring("Quadratically",5,6);          -> ratica

`SUBSTRING_INDEX(String, Delimiter, Count)'
     Returns the substring from `String' after `Count' `Delimiters'. If
     `Count' is positive the strings are searched from left else if
     count is negative the substrings are searched and returned from
     right.
          mysql> select substring_index("www.tcx.se", ".", 2);   -> "www.tcx"
          mysql> select substring_index("www.tcx.se", ".", -2);  -> "tcx.se"

`SPACE(N)'
     Return a string of `N' spaces.
          mysql> select SPACE(6);         -> "      "

`REPLACE(A, B, C)'
     Replaces all occurrences of string `B' in string `A' with string
     `C'.
          mysql> select replace("www.tcx.se", "w", "Ww");  -> "WwWwWw.tcx.se"

`REPEAT(String, Count)'
     Repeats `String' `Count' times. If `Count <= 0' returns a empty
     string. If `String' or `Count' is `NULL' or `LENGTH(string)*count
     > max_allowed_size' returns `NULL'.
          mysql> select repeat("MySQL", 3);                -> "MySQLMySQLMySQL"

`REVERSE(String)'
     Reverses all characters in string.
          mysql> select reverse("abc");  -> "cba"

`INSERT(Org, Start, Length, New)'
     Replaces substring in `Org' starging at `Start' and `Length' long
     with `New'. First position in `Org' is numbered 1.
          mysql> select insert("Quadratic", 3, 4, "What");   -> "QuWhattic"

`INTERVAL(N, N1, N2, N3...)'
     It is required that `Nn' > `N3' > `N2' > `N1' is this function
     shall work. This is because a binary search is used (Very fast).
     Returns 0 if `N' < `N1', 1 if `N' < `N2' and so on. All arguments
     are treated as numbers.
          mysql> select INTERVAL(23, 1, 15, 17, 30, 44, 200);     -> 3
          mysql> select INTERVAL(10, 1, 10, 100, 1000);           -> 2
          mysql> select INTERVAL(22, 23, 30, 44, 200);            -> 0

`LCASE(A)'
`LOWER(A)'
     Changes `A' to lower case according to current character set
     ,dmappings (Default Latin1).
          mysql> select lcase("QUADRATICALLY");           -> "quadratically"

`UCASE(A)'
`UPPER(A)'
     Changes `A' to upper case.
          mysql> select ucase("Hej");             -> "HEJ"

`ELT(N, A1, A2, A3...)'
     Returns `A1' if `N' = 1, `A2' if `N' = 2 and so on. If `N' is less
     than 1 or bigger than the number of arguments `NULL' is returned.
          mysql> select elt(1, "ej", "Heja", "hej", "foo");  -> "ej"
          mysql> select elt(4, "ej", "Heja", "hej", "foo");  -> "foo"

`FIELD(S, S1, S2, S3...)'
     Returns index of `S' in `S1', `S2', `S3'... list. The complement
     of `ELT()'.
          mysql> select ELT(2, "Hej", "ej", "Heja", "hej", "foo");                -> "ej"
          mysql> select ELT(-2, "Hej", "ej", "Heja", "hej", "foo");               -> NULL

Date and time functions
-----------------------

   Some examples using more than one date function:

   Select all record with a date_field from the last 30 days.
     SELECT something FROM table WHERE NOW() >
             FROM_DAYS(TO_DAYS(date_field) + 30);

`PERIOD_ADD(P, N)'
     Adds `N' months to period `P' (of type `YYMM' or `YYYYMM').
     Returns `YYYYMM'.
          mysql> select PERIOD_ADD(9801,2);               -> 199803

`PERIOD_DIFF(A, B)'
     Returns months between periods `A' and `B'. `A' and `B' should be
     of format `YYMM' or `YYYYMM'.
          mysql> select PERIOD_DIFF(9802,199703);         -> 11

`TO_DAYS(Date)'
     Changes a `Date' to a daynumber (Number of days since year 0).
     `Date' may be a `DATE' string, a `DATETIME' string, a
     `TIMESTAMP([6 | 8 | 14])' or a number of format `YYMMDD' or
     `YYYYMMDD'.
          mysql> select TO_DAYS(9505);                    -> 733364
          mysql> select TO_DAYS('1997-10-07);             -> 729669

`FROM_DAYS()'
     Changes a daynumber to a DATE.
          mysql> select from_days(729669);                -> 1997-10-07

`DATE_FORMAT(Date, Format)'
     Formats the `Date' (a date or a timestamp) according to the
     `Format' string. The following format commands are known:      M       Month name                                                   
     W       Weekday name                                                 
     D       Day of the month with english suffix                         
     Y       Year with 4 digits                                           
     y       Year with 2 digits                                           
     m       Month                                                        
     d       Day of the month                                             
     h       hour                                                         
     i       Minutes                                                      
     s       Seconds                                                      
     w       Day of the week (0=Monday..)                                 



     All other characters are copied to the result.
          mysql> select date_format('1997-10-04 22:23:00', "W M Y h:i:s");
                  -> "Saturday October 1997 22:23:00"

`WEEKDAY(Date)'
     Gets weekday for `Date' (0 = Monday, 1 = Tuesday ..). `Date' may
     be a date string, a datetime string, a timestamp([6 | 8 | 14]) or a
     number of format `YYMMDD' or `YYYYMMDD'.
          mysql> select WEEKDAY('1997-10-04 22:23:00');           -> 5
          mysql> select WEEKDAY('1997-11-05');                    -> 2

`CURDATE()'
`CURRENT_DATE()'
     Returns todays date. In form `YYYYMMDD' or `"YYYY-MM-DD"'
     depending on whether `CURDATE()' is used in a number or string
     context.
          mysql> select CURDATE();                -> "1997-12-15"
          mysql> select CURDATE()+0;              -> 19971215

`CURTIME()'
`CURRENT_TIME()'
     Returns current time in form `HHMMSS' or `"HH:MM:SS"', depending
     on whether `CURTIME()' is used in a number or string context.
          mysql> select CURTIME();                -> "23:50:20"
          mysql> select CURTIME()+0;              -> 235026

`NOW()'
`SYSDATE()'
`CURRENT_TIMESTAMP()'
     Returns the current time in format `YYYYMMDDHHMMSS' or
     `"YYYY-MM-DD HH:MM:SS"' depending on whether `NOW()' is used in a
     number or string context.
          mysql> select NOW();            -> "1997-12-15 23:51:26"
          mysql> select NOW()+0;          -> 19971215235131

`UNIX_TIMESTAMP([Date])'
     If called without any arguments returns the current time as a unix
     timestamp (seconds in GMT since 1970.01.01 00:00:00). Normally it
     is called with a `TIMESTAMP' column as an argument in which case it
     returns the columns value in seconds. `Date' may also be a date
     string, a datetime string, or a number of format YYMMDD or YYYMMDD
     in local time.
          mysql> select UNIX_TIMESTAMP();                         -> 882226357
          mysql> select UNIX_TIMESTAMP('1997-10-04 22:23:00');    -> 875996580

`FROM_UNIXTIME(Unix_timestamp)'
     Returns a string of the timestamp in `YYYY-MM-DD HH:MM:SS' or
     `YYYYMMDDHHMMSS' format depending on context (numeric/string).
          mysql> select FROM_UNIXTIME(875996580);   -> "1997-10-04 22:23:00"

`FROM_UNIXTIME(Unix_timestamp, Format_string)'
     Returns a string of the timestamp formated according to the
     Format_string. The format string may contain:      `M'           Month, textual                                         
     `W'           Day (of the week), textual                             
     `D'           Day (of the month), numeric plus english suffix        
     `Y'           Year, numeric, 4 digits                                
     `y'           Year, numeric, 2 digits                                
     `m'           Month, numeric                                         
     `d'           Day (of the month), numeric                            
     `h'           Hour, numeric                                          
     `i'           Minutes, numeric                                       
     `s'           Seconds, numeric                                       
     `w'           Day (of the week), numeric                             
     All other     All other characters are just copied.                  



          mysql> select FROM_UNIXTIME(UNIX_TIMESTAMP(), "Y D M h:m:s x");
                  -> "1997 23rd December 03:12:30 x"

`SEC_TO_TIME(Seconds)'
     Returns the hours, minutes and seconds of the argument in `H:MM:SS'
     or `HMMSS' format depending on context.
          mysql> select SEC_TO_TIME(2378);                -> "00:39:38"
          mysql> select SEC_TO_TIME(2378)+0;              -> 3938

`TIME_TO_SEC(Time)'
     Converts `Time' to seconds.
          mysql> select TIME_TO_SEC('22:23:00');  -> 80580
          mysql> select TIME_TO_SEC('00:39:38');  -> 2378

Miscellaneous functions.
------------------------

`DATABASE()'
     Returns current database name.
          mysql> select DATABASE();               -> "test"

`USER()'
`SYSTEM_USER()'
`SESSION_USER()'
     Returns current user name.
          mysql> select USER();                   -> "davida"

`PASSWORD(String)'
     Calculates a password string from plaintext password `String'. This
     must be used to store a password in the 'user' grant table.
          mysql> select PASSWORD("badpwd");       -> "7f84554057dd964b"

`ENCRYPT(String[, Salt])'
     Crypt `String' with the unix `crypt()' command. The `Salt' should
     be a string with 2 characters. If `crypt()' was not found `NULL'
     will always be returned.

`LAST_INSERT_ID()'
     Returns the last automaticly generated value that was set in a
     auto_increment column. *Note mysql_insert_id::.
          mysql> select LAST_INSERT_ID();         -> 1

`FORMAT(Nr, Num)'
     Formats number `Nr' to a Format like '#,###,###.##' with `Num'
     decimals.
          mysql> select FORMAT(12332.33, 2);      -> "12,332.33"

`VERSION'
     Return the version of the *MySQL* server.
          mysql> select version();                -> "3.21.16-beta-log"

Functions for `GROUP BY' clause.
--------------------------------

`COUNT(Expr)'
     Count number of non `NULL' rows. `count(*)' is optimised to return
     very quickly if no other column is used in the `SELECT'.
          select count(*) from student;
          select count(if(length(name)>3,1,NULL)) from student;

`AVG(expr)'
     Average value of expr.

`MIN(expr)'
`MAX(expr)'
     Minimum/Maximum value of expr. `min()' and `max()' may take a
     string argument and will then return the minimum/maximum string
     value.

`SUM(expr)'
     Sum of expr.

`STD(expr)'
     Standard derivation of expression. This is a extension to `ANSI
     SQL'.

`BIT_OR(expr)'
     The bitwise `OR' of all bits in expr. Caclulation done with 64 bits
     precision.

`BIT_AND(expr)'
     The bitwise `AND' of all bits in expr. Caclulation done with 64
     bits precision.

   MySQL has extended the use of `GROUP BY'. You can use columns or
calculations in the `SELECT' expressions which doesn't appear in the
`GROUP BY' part. This stands for 'any possible value for this group'.
By using this, one can get a higher performance by avoiding sorting and
grouping on unnecessary items.  For example, in the following query one
doesn't need to sort on b.name:

     SELECT a.id,b.name,COUNT(*) from a,b WHERE a.id=b.id GROUP BY a.id

Create database syntax.
=======================

     CREATE DATABASE database_name

   Creates a database with the given name. The name can only contain
letters, numbers or the `'_'' character. The max length of the database
name is 32 characters.  All databases in *MySQL* are directories, so a
CREATE DATABASE only creates a directory in the *MySQL* database
directory.  You can also create databases with `mysqladmin'.  *Note
Programs::

Create database syntax.
=======================

     DROP DATABASE database_name

   Drop all tables in the database and deleted the database.  *You have
to be VERY carefull with this command!* `DROP DATABASE' returns how
many files was removed from the directory.  Normally this is number of
tables*3.  You can also drop databases with `mysqladmin'.  *Note
Programs::

CREATE TABLE syntax.
====================

     CREATE TABLE table_name ( create_definition,... )
     
     create_definition:
       column_name type [DEFAULT default_value] [NOT NULL | NULL] [ PRIMARY KEY ]
                        [reference_definition]
       or	PRIMARY KEY ( index_column_name,... )
       or	KEY [key_name] KEY( index_column_name,...)
       or	INDEX [index_name] ( index_column_name,...)
       or	UNIQUE [index_name] ( index_column_name,...)
       or    FOREIGN KEY index_name ( index_column_name,...) [reference_definition]
       or	CHECK (expr)
     
     index_column_name:
     	column_name [ (length) ]
     
     reference_definition:
     	REFERENCES table_name [( index_column_name,...)]
                        [ MATCH FULL | MATCH PARTIAL]
                        [ ON DELETE reference_option]
                        [ ON UPDATE reference_option]
     
     reference_option:
             RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT

   The FOREIGN KEY, CHECK and REFERENCE syntax are only for
compatibility.  They don't actually do anything. *Note Missing
functions::

   If a column doesn't have a DEFAULT value and is not declared as NOT
NULL, the default value is NULL.

   * ZEROFILL means that number is pre-zeroed to maximal length. With
     `INT(5) ZEROFILL' a value of 5 is retrieved as `00005'.

   * `BINARY' means that the column will be compared case sensitive. The
     default is that all strings are compared case insensitive. `BINARY'
     is 'sticky' which means that if a column marked `BINARY' is used in
     a expression, the whole expression is compared `BINARY'.

   * KEY is only a synonym for INDEX.

   * If one doesn't assign a name to a index, the index will get the
     same name as the first key_column with an optional _# to make it
     unique.

   * Index columns and timestamp columns can't be NULL. For these
     columns the NULL attribute is silently removed.

   * With `column_name(length)' syntax one can specify a index which is
     only a part of a `string' column. This can make the index file
     much smaller.

   * A number column may have the additional attribute AUTO_INCREMENT
     to automatically get the largest value+1 for each insert where
     column value is NULL or 0. *Note mysql_insert_id::

   * One can insert NULL for timestamp and auto_increment columns. This
     results in the current time / the next number.

   * Blob columns can't be index.

   * When one groups on a blob only the first 'max_sort_length' bytes
     are used. *Note BLOB Limitations::.

   * Deleted records are in a linked list and subsequent inserts will
     reuse old positions. To get smaller files one can use the
     `isamchk' utility to reorganise tables.

   * Each null column takes 1 bit extra, rounded up to the nearest byte.

   * The maximum record length can be calculated as follows: 1+
     sum_of_column_lengths + null_columns/8 + number of variable length
     columns.

   * In some cases an attribute may silently change after creation:
     `VARCHAR' columns with a length of 1 or 2 are changed to `CHAR'.
     When using one `VARCHAR' column all `CHAR' columns longer than 2
     are changed to `VARCHAR''s.

   * On `INSERT'/`UPDATE' all strings (`CHAR' and `VARCHAR') are
     silently chopped/padded to the maximal length given by CREATE. All
     end spaces are also automatically removed. For example
     `VARCHAR(10)' means that the column can contain strings with a
     length up to 10 characters.

   * Something/0 gives a `NULL' value.

   * The regular expression function (`REGEXP' and `RLIKE') uses
     ISO8859-1 (Latin1) when deciding the type of a character.

ALTER TABLE syntax
==================

     ALTER [IGNORE] TABLE table_name alter_spec [, alter_spec ...]
     
     alter_specification:
     	ADD [COLUMN] create_definition
     or	CHANGE [COLUMN] old_column_name create_definition
     or	ALTER [COLUMN] column_name { SET DEFAULT literal | DROP DEFAULT }
     or	DROP [COLUMN] column_name
     or	DROP PRIMARY KEY
     or	DROP INDEX key_name
     or	RENAME TABLE AS new_table_name

   * `ALTER TABLE' works by creating a temporary table and copying all
     information to it and then the old table is deleted and the new
     one is renamed. This is done in such a way that all updates are
     automatically redirect to the new table without any failed
     updates. While the `ALTER TABLE' is working, the old table is
     readable for other clients. Table updates/writes to the table are
     stalled and only executed after the new table is ready.

   * If `IGNORE' isn't specified then the copy will be aborted and
     rolled back if there exists any duplicated unique index in the new
     table. This is a *MySQL* extension.

   * The `CHANGE column_name', `DROP column_name' and `DROP INDEX' are
     *MySQL* extensions to ANSI SQL92.

   * The optional word `COLUMN' is a pure noise word and can be omitted.

   * The `ADD' and `CHANGE' takes the same create_definition as `CREATE
     TABLE'. *Note Create table::.

   * `ALTER COLUMN' sets a new default value or removes the old default
     value for a column.

   * `DROP INDEX' removes an index. This is an *MySQL* extension.

   * The `FOREIGN KEY' syntax in *MySQL* exists only for compatibility.
     *Note Missing functions::

   * If one drops a column_name which is part of some index, this index
     part is removed. If all index parts are removed then the index is
     removed.

   * `DROP PRIMARY KEY' drops index named `PRIMARY' or if no such index
     exists, it drops the first `UNIQUE' index in the table.

   * `CHANGE' tries to convert data to the new format as good as
     possible.

   * With `mysql_info(MYSQL*)' one can retrieve how many records were
     copied and how many records were deleted because of multiple
     indexes.

   * To use `ALTER TABLE' one has to have select, insert, delete,
     update, create and drop privileges on the table.

   * If one uses `ALTER TABLE table_name RENAME AS new_name' without any
     other options, *MySQL* will only do a fast rename of table table.

DROP TABLE syntax.
==================

   `DROP TABLE table_name [, table_name...]'

   Removes one or more tables. All the data and the definition is
*removed* so take it easy with this command!

DELETE syntax.
==============

   `DELETE FROM table_name WHERE where_definition'

   Returns records affected.

   If one does a delete without a where clause then the table is
recreated which is much faster than doing a delete for each row. In
these cases, the SQL command returns zero as affected records.

   Using `DELETE FROM table_name' will work even if the data files do
not exist as only information from the table definition file,
`table_name.frm', is used.

   * All string comparisons are case independent with case according to
     ISO-8859-1 Latin1.

   * LIKE is allowed on numerical columns.

   * Compare with explicit NULL (column = NULL) is the same as if IS
     NULL was used (column IS NULL). This is is done to be consistent
     with `mSQL'.

SELECT syntax
=============

   `SELECT [STRAIGHT_JOIN] [DISTINCT | ALL] select_expression,... [INTO
OUTFILE 'file_name' ...] [ FROM table_references [WHERE
where_definition ] [GROUP BY column,...] [ ORDER BY column [ASC | DESC]
,..] HAVING where_definition [LIMIT [offset,] rows] [PROCEDURE
procedure_name]] '

   Strings are automatically converted to numbers and numbers to strings
when needed (a-la Perl). If in a compare operation (`(=, <>, <= ,<, >=,
>)') either of the arguments are numerical, the arguments are compared
as numbers, else the arguments are compared as strings. All string
comparisons are by default done case-independent by ISO8859-1 (The
Scandinavian letter set which also works excellently with English).

     select 1 > "6x";        ->      0
     
     select 7 > "6x";        ->      1
     
     select 0 > "x6";        ->      0
     
     select 0 = "x6";        ->      1

   - A column name does not have to have a table prefix if the given
     column name is unique.

   - A select expression may be given an alias which will be its column
     name and can be used when sorting and grouping or in the `HAVING'
     clause.
          select concat(last_name,' ',first_name) as name from table order by name

   - Table_references is a list of tables to join. This may also contain
     `LEFT OUTER JOIN' references.  *Note Join::

   - In LIKE expressions % and _ may be preceded with '\' to skip the
     wild-card meaning and get a literal % or _.

   - A DATE is a string with one of the following syntaxes:
        - YYMMDD        (Year is assumed to be 2000 if YY < 70.)

        - YYYYMMDD

        - YY.MM.DD	Where '.' may be any non numerical separator.

        - YYYY.MM.DD	Where '.' may be any non numerical separator.

   - `IFNULL()' and `IF()' returns number or string value according to
     use.

   - `ORDER' and `GROUP' columns may be given as column names, column
     alias or column numbers in `SELECT' clauses.

   - The `HAVING' clause can take any columns or alias in the
     select_expressions. It is applied last, just before items are sent
     to the client, without any optimisation. Don't use it for items
     that should be in the WHERE clause. You can't write (yet):

          `SELECT user,MAX(salary) FROM users GROUP BY users HAVING max(salary)>10'

     Change it to:

          `SELECT user,MAX(salary) AS sum FROM users GROUP BY users HAVING sum > 10'

   - `STRAIGHT_JOIN' forces the optimiser to join the tables in the same
     order that the tables are given in the `FROM' clause. One can use
     this to get a query to be done more quickly if the optimiser joins
     the tables in not optimal order. *Note Explain::

   - LIMIT takes one or two numerical arguments.
        * If one argument, the argument indicates the maximum number of
          rows in a result.

        * If two arguments, the first argument says the offset to the
          first row to return, the second is the maximum number of rows.

   - INTO OUTFILE 'filename' writes the given set to a file. The file
     can not exist from before. *Note Load::.

Join syntax
===========

   *MySQL* supports the following `JOIN' syntaxes:

     table_reference, table_reference
     table_reference [CROSS] JOIN table_reference
     table_reference LEFT [OUTER] JOIN table_reference ON conditional-expr
     table_reference LEFT [OUTER] JOIN table_reference USING (column-commalist)
     table_reference NATURAL LEFT [OUTER] JOIN table_reference
     { oj table_reference LEFT OUTER JOIN table_reference ON conditional-expr }

   * A table reference may be aliased with `table_reference AS alias' or
     `table_reference alias'.

   * `,' and `JOIN' are semantically identical.  This does a full join
     between the used tables.  One normally specifies in the `WHERE'
     condition how the tables should be linked.

   * The `ON' conditional is any `WHERE' conditional.  If there is no
     matching record in for the right table in a `LEFT JOIN' a row with
     all columns set to NULL will be used for the right table.

   * The `USING' column-list is a list of fields that must exists in
     both tables.  `A LEFT JOIN B USING (C1,C2,C3...)' is defined to be
     semantically identical to using a `ON' expression ` A.C1=B.C1 AND
     A.C2=B.C2 AND A.C3=B.C3... '.

   * The `NATURAL LEFT JOIN' of two tables is defined to be semantically
     identical to a `USING' with all column names that exists in both
     tables.

   * The last `LEFT JOIN' syntax is only to be compatible with ODBC.

INSERT syntax
=============

     	INSERT INTO table [ (column_name,...) ] VALUES (expression,...)
     or	INSERT INTO table [ (column_name,...) ] SELECT ...

   An expression may use any previous column in column_name list (or
table if no column name list is given).

   The following holds for a multi-row `INSERT' statement:
   - The query cannot contain an `ORDER BY' clause.

   - The target table of the `INSERT' statement cannot appear in the
     FROM clause of the query.

   - If one uses `INSERT INTO ... SELECT ...' then one can get the
     following info string with the C API function `mysql_info()'.

     `Records: 100 Duplicates: 0 Warnings: 0' Duplicates are number of
     rows which couldn't be written because some index would be
     duplicated. Warnings are columns which were set to NULL, but have
     been declared NOT NULL. These will be set to their default value.

   - If one sets a time stamp value to anything other than NULL, the
     time stamp value will be copied to the result table.

   - Auto increment columns works as usual.

REPLACE syntax
==============

     	REPLACE INTO table [ (column_name,...) ] VALUES (expression,...)
     or	REPLACE INTO table [ (column_name,...) ] SELECT ...

   This works exactly like `INSERT', except that if there was some old
record in the table with the same unique index the old record or records
will be deleted before this record is inserted.  *Note Insert::.

LOAD DATA INFILE syntax
=======================

   `LOAD DATA INFILE' 'text_file_name.text' [`REPLACE' | `IGNORE']
`INTO' `TABLE' table_name [`FIELDS' [`TERMINATED BY' ',' [`OPTIONALLY']
`ENCLOSED BY' '"' `ESCAPED BY' '\\' ]] [`LINES TERMINATED BY' '\n']
[(Field1, Field2...)]

   This is used to read rows from a text file, which must be located on
the server, at a very high speed. The server-client protocol doesn't yet
support files over a connection. If you only have the file on the
client, use rcp or ftp to copy it, possibly compressed, to the server
before using `LOAD DATA INFILE'. All paths to the text file are
relative to the database directory.

   To write data to a text file, use the `SELECT ... INTO OUTFILE
'interval.txt' fields terminated by ',' enclosed by '"' escaped by '\\'
lines terminated by '\n' FROM ...'  syntax.

   Normally you don't have to specify any of the text file type
options. The default is a compact text file with columns separated with
`tab' characters and all rows end with a newline. Tabs, newlines and `\'
inside fields are prefixed with a `\'. NULL's are read and written as
\N.

   `FIELDS TERMINATED BY' has the default value of `\t'.

   `FIELDS [OPTIONALLY] ENCLOSED BY' has the default value of `'''.

   `FIELDS ESCAPED BY' has the default value of `'\\''.

   `LINES TERMINATED BY' has the default value of `'\n''.

   `FIELDS TERMINATED BY' and `LINES TERMINATED BY' may be more than 1
character.

   If `LINES TERMINATED BY' is an empty string and `FIELDS TERMINATED
BY' is not empty then lines are also terminated with `FIELDS TERMINATED
BY'.

   If `FIELDS TERMINATED BY' and `FIELDS ENCLOSED BY' both are empty
strings (`''') then this gives a fixed row format ("not delimited"
import format). With a fixed row size NULL values are outputed as a
blank string.

   If you specify `OPTIONALLY' in `ENCLOSED BY', then only strings are
enclosed in `ENCLOSED BY' by the `SELECT ... INTO' statement.

   Duplicated `ENCLOSED BY' chars are removed from strings that start
with `ENCLOSED BY'. For example: With `ENCLOSED BY '"'':
     "The ""BIG"" boss"  -> The "BIG" boss
     The "BIG" boss	    -> The "BIG" boss

   If `ESCAPED BY' is not empty then the following characters will be
prefixed with the escape character: `ESCAPED BY', `ASCII 0', and the
first character in any of `FIELDS TERMINATED BY', `FIELDS ENCLOSED BY'
and `LINES TERMINATED BY'.

   If `FIELDS ENCLOSED BY' is not empty then `NULL' is read as a `NULL'
value. If `FIELDS ESCAPED BY' is not empty then `\N' is also read as a
`NULL' value.

   If `REPLACE' is used, then the new row will replace all rows which
have the same unique index. If `IGNORE' is used, the row will then be
skipped if there already exist a record with an identical unique index.
If none of the above options are used an error will be issued. The rest
of the text file will be ignored if one gets a duplicate index error.

   Some possible cases that are not supported by `LOAD DATA':
   * Fixed size rows (`FIELDS TERMINATED BY' and `FIELDS ENCLOSED BY'
     both are empty) and BLOB columns.

   * If some of the separators are a prefix of another.

   * `FIELDS ESCAPED BY' is empty and the data contains `LINES
     TERMINATED BY' or `FIELDS ENCLOSED BY' followed by `FIELDS
     TERMINATED BY'.

   All rows are read into the table. If a row has too few columns, the
rest of the columns are set to default values.

   For security reasons the text file must either reside in the database
directory or be readable by all.

   For more information about the escaped syntax, *Note Base Syntax::.

   When the `LOAD DATA' query is done, one can get the following info
string with the C API function `mysql_info()'.

   `Records: 1 Deleted: 0 Skipped: 0 Warnings: 0'

   Warnings are incremented for each column which can't be stored
without loss of precision, for each column which didn't get a value
from the read text line (happens if the line is too short) and for each
line which has more data than can fit into the given columns.

   An example that loads all columns:

     LOAD DATA INFILE 'persondata.text' INTO TABLE persondata;

   *Note Table efficiency::

UPDATE syntax
=============

   UPDATE table SET column=expression,... WHERE where_definition

   All updates are done from left to right. If one accesses a column in
the expression, update will then use the current value (a given value
or the default value) of the column.

     UPDATE persondata SET count=count+1

SHOW syntax. Get information about names of columns.
====================================================

     	SHOW DATABASES [LIKE wild]
     or 	SHOW TABLES [FROM database] [LIKE wild]
     or	SHOW COLUMNS FROM table [FROM database] [LIKE wild]
     or	SHOW INDEXES FROM table [FROM database]

   Gives information about databases, tables or columns. If the `LIKE
wild' part is used the `wild' string is a normal SQL wildcard (with %
and _). `FIELDS' may be used as an alias for `COLUMNS' and `KEYS' may
be used as an alias for `INDEXES'.

EXPLAIN syntax. Get information about a SELECT.
===============================================

     	EXPLAIN SELECT select_options

   Gives information about how and in which order tables are joined.
With the help of `EXPLAIN' one can see when one has to add more indexs
to tables to get a faster select that uses indexs to find the records.
You can also see if the optimiser joins the tables in an optimal order.
One can force the optimiser to use a specific join order with the
`STRAIGHT_JOIN' option to select.

   The different join types are:

`system'
     The table has only 1 record (= system table)

`const'
     The table has at most 1 matching record which will be read at the
     start of the query. All columns in this table will be regarded as
     constants by the rest of the optimiser.

`eq_ref'
     One record will be read from this table for each combination of
     the previous tables.

`ref'
     All records with matching indexs will be read from this table for
     each combination of the previous tables.

`all'
     A full table scan will be done for each combination of the
     previous tables.

   Here is a example of a join which is optimized with the help of
`EXPLAIN'.

     EXPLAIN SELECT tt.TicketNumber, tt.TimeIn,
             tt.ProjectReference, tt.EstimatedShipDate,
             tt.ActualShipDate, tt.ClientID,
             tt.ServiceCodes, tt.RepetitiveID,
             tt.CurrentProcess, tt.CurrentDPPerson,
             tt.RecordVolume, tt.DPPrinted, et.COUNTRY,
             et_1.COUNTRY, do.CUSTNAME
             FROM tt, et, et AS et_1,
             do
             WHERE tt.SubmitTime Is Null and tt.ActualPC =
             et.EMPLOYID and tt.AssignedPC =
             et_1.EMPLOYID and tt.ClientID =
             do.CUSTNMBR;

   The `EXPLAIN' returns the following:

     table   type    possible_keys   key     key_len ref     rows    Extra
     et      ALL     PRIMARY NULL    NULL    NULL    74
     do      ALL     PRIMARY NULL    NULL    NULL    2135
     et_1    ALL     PRIMARY NULL    NULL    NULL    74
     tt      ALL     AssignedPC,ClientID,ActualPC    NULL    NULL    NULL   3872
             range checked for each record (key map: 35)

   In this case *MySQL* is doing a full join for all tables! This will
take quite a long time as the product of the number of rows in each
table must be examined!. So if all tables had 1000 records *MySQL* has
to look at 1000^4 = 1000000000000 rows. And if the tables are bigger
you can only imagine how long it would take...

   In this case the first error is that *MySQL* can't yet use
efficiently indexes on columns that are declared differently: (varchar()
and char() are not different in this context)

   In this case `tt.ActualPC' is `char(10)' and `et.EMPLOYID' is
`char(15)'.

   Fix:

     mysql> alter table tt change ActualPC ActualPC varchar(15);

   And the above explain shows:

     table   type    possible_keys   key     key_len ref     rows    Extra
     tt      ALL     AssignedPC,ClientID,ActualPC    NULL    NULL    NULL   3872
             where used
     do      ALL     PRIMARY NULL    NULL    NULL    2135
             range checked for each record (key map: 1)
     et_1    ALL     PRIMARY NULL    NULL    NULL    74
             range checked for each record (key map: 1)
     et     eq_ref  PRIMARY PRIMARY 15      tt.ActualPC    1

   Which is not perfect but much better. This version is executed in a
couple of seconds.

   After

     mysql> alter table tt change AssignedPC AssignedPC varchar(15),
                           change ClientID Clientid     varchar(15);

   You get the following from `EXPLAIN':

     table   type    possible_keys   key     key_len ref     rows    Extra
     et      ALL     PRIMARY NULL    NULL    NULL    74
     tt      ref     AssignedPC,ClientID,ActualPC    ActualPC        15
             et.EMPLOYID   52      where used
     et_1    eq_ref  PRIMARY PRIMARY 15      tt.AssignedPC  1
     do      eq_ref  PRIMARY PRIMARY 15      tt.Clientid    1

   Which is 'almost' as good as it can get.  The problem is that
*MySQL* assumes that `tt.AcutalPC' is evenly distributed which isn't
the case in the tt.

   Fortunally it easy to tell *MySQL* about this:

     shell> isamchk -a PATH_TO_MYSQL_DATABASE/tt
     shell> mysqladmin refresh

   And now the join is 'perfect':

     table   type    possible_keys   key     key_len ref     rows    Extra
     tt      ALL     AssignedPC,ClientID,ActualPC    NULL    NULL    NULL
             3872     where used
     et      eq_ref  PRIMARY PRIMARY 15      tt.ActualPC    1
     et_1    eq_ref  PRIMARY PRIMARY 15      tt.AssignedPC  1
     do      eq_ref  PRIMARY PRIMARY 15      tt.Clientid    1

DESCRIBE syntax. Get information about columns.
===============================================

   `(DESCRIBE | DESC) table [column]'

   Gives information about columns. This command is for Oracle
compatibility. *Note Show::. Column may be a column name or a string.
Strings may contain wild cards.

`LOCK TABLES' syntax
====================

     LOCK TABLES table_name [AS alias] READ|WRITE [, table_name READ|WRITE]
     ...
     UNLOCK TABLES

   Locks tables for this thread. Many threads may have a READ lock on
the same table, but one can use a table with a WRITE lock.  One can't
update a table on which one has a read LOCK.  When one uses `LOCK
TABLES' one must lock all tables one is going to use!

     LOCK TABLES t READ, t as t2 READ
     SELECT * from t,t2;

   All tables are automaticly unlocked when one issues another `LOCK
TABLES' or if the connection to the server is closed.

SET OPTION syntax.
==================

     SET [OPTION] SQL_VALUE_OPTION=value, ...

   The used options remain in effect for the whole current session.

   The different options are:

`SQL_SELECT_LIMIT=value'
     The maximum number of records to return in any select.  If a
     select has a limit clause it overrides this statement.  The
     default value for a new connection is 'unlimited'.

`SQL_BIG_TABLES= 0 | 1'
     If set to 1 then all temporary tables are stored on disk based.
     This will be a little slower, but one will not get the error `The
     table ### is full' anymore for big selects that require a big
     temporary tables.  The default value for a new connection is 0
     (use in memory temporary tables).

`SQL_BIG_SELECTS= 0 | 1'
     If set to 1 then *MySQL* will aborts if one will try to make a
     select with probably will take a very long time. This is a nice to
     terminate SELECTS with a erroneous `WHERE' statement. A big query
     is defined as a `SELECT' that will probably have to examine more
     than `max_join_size' rows.  The default value for a new connection
     is 0 (allow all SELECT's).

`SQL_LOG_OFF= 0 | 1'
     If set to 1 then no logging will done to the standard log for this
     client if the client has process list privileges.  This doesn't
     affect the update log!

`TIMESTAMP= timestamp_value | DEFAULT'
     Set the time for this client.  This is used to get the original
     timestamp if one uses the update log to restore rows.

`LAST_INSERT_ID= #'
     Set the value to be returned from LAST_INSERT_ID(). This is stored
     in the update log when one uses LAST_INSERT_ID() in a command that
     updates a table.

GRANT syntax. (Compatibility function).
=======================================

     GRANT (ALL PRIVILEGES | (SELECT, INSERT, UPDATE, DELETE,
      REFERENCES (column list), USAGE))
      ON table TO user,... [WITH GRANT OPTION]

   This command doesn't do anything. It is only in *MySQL* for
compatibility reasons. Privileges in *MySQL* is handled with the mysql
grant tables. *Note Privileges::

CREATE INDEX syntax (Compatibility function).
=============================================

   `CREATE [UNIQUE] INDEX index_name ON table_name ( column_name,... )'

   This function doesn't do anything. It is only in *MySQL* for
compatibility reasons.  You can create new index with ALTER TABLE.
*Note Alter table::

DROP INDEX syntax (Compatibility function).
===========================================

   `DROP INDEX index_name'

   This always succeeds.  You can drop an index with ALTER TABLE. *Note
Alter table::

Is *MySQL* picky about reserved words?
======================================

   A common problem stems from trying to create a table with column
names `timestamp' or `group', the names of datatypes and functions
built into *MySQL*.  You're allowed to do it (for example, `ABS' is an
allowed column name), but whitespace is not allowed between a function
name and the `'('' when using the functions whose names are also column
names.

   The following are explictly reserved words in *MySQL*. Most of them
(for example) `group', are forbidden by ANSI SQL92 as column and/or
table names. A few are because *MySQL* needs them and is (currently)
using a Yacc parser:

`action'           `add'              `all'              `alter'            
`and'              `as'               `asc'              `auto_increment'   
`between'          `bigint'           `bit'              `binary'           
`blob'             `both'             `by'               `cascade'          
`char'             `character'        `change'           `check'            
`column'           `columns'          `create'           `data'             
`database'         `databases'        `date'             `datetime'         
`day'              `day_hour'         `day_minute'       `day_second'       
`dayofweek'        `dec'              `decimal'          `default'          
`delete'           `desc'             `describe'         `distinct'         
`double'           `drop'             `escaped'          `enclosed'         
`enum'             `explain'          `fields'           `float'            
`float4'           `float8'           `foreign'          `from'             
`for'              `full'             `grant'            `group'            
`having'           `hour'             `hour_minute'      `hour_second'      
`ignore'           `in'               `index'            `infile'           
`insert'           `int'              `integer'          `interval'         
`int1'             `int2'             `int3'             `int4'             
`int8'             `into'             `is'               `join'             
`key'              `keys'             `leading'          `left'             
`like'             `lines'            `limit'            `lock'             
`load'             `long'             `longblob'         `longtext'         
`match'            `mediumblob'       `mediumtext'       `mediumint'        
`middleint'        `minute'           `minute_second'    `month'            
`natural'          `numeric'          `no'               `not'              
`null'             `on'               `option'           `optionally'       
`or'               `order'            `outer'            `outfile'          
`partial'          `precision'        `primary'          `procedure'        
`privileges'       `read'             `real'             `references'       
`rename'           `regexp'           `repeat'           `replace'          
`restrict'         `rlike'            `select'           `set'              
`show'             `smallint'         `sql_big_tables'   `sql_big_selects'  
`sql_select_limit' `sql_log_off'      `straight_join'    `starting'         
`table'            `tables'           `terminated'       `text'             
`time'             `timestamp'        `tinyblob'         `tinytext'         
`tinyint'          `trailing'         `to'               `use'              
`using'            `unique'           `unlock'           `unsigned'         
`update'           `usage'            `values'           `varchar'          
`varying'          `varbinary'        `with'             `write'            
`where'            `year'             `year_month'       `zerofill'         

   The following symbols (from the table above) are disallowed by ANSI
SQL but allowed by *MySQL* as column/table names. This is because some
of theese names are very natural names so a lot of people has already
used them.

   * ACTION

   * BIT

   * DATE

   * ENUM

   * NO

   * TEXT

   * TIME

   * TIMESTAMP

How safe/stable is *MySQL*
**************************

How stable is *MySQL*?
======================

   At TcX, *MySQL* has worked without any problems in our projects
since mid 1996. When released to a wider public we noticed that there
were some parts of 'untested code' in *MySQL* that were quickly found
by the new user group who made queries in a different manner.  Each new
release has had fewer portability problems than the previous one, even
though they have all had a lot of new features, and we hope that it
will be possible to label one of the next releases 'stable'.

   Each release of *MySQL* has been usable and there has only been
problems when users start to use code from 'the gray zones'. Naturally,
outside users can't know what the gray zones are and I hope this section
will clarify those currently known.

   We will here try to answer some of the more important questions that
seems to concern a lot of people and clarify some issues. This section
has been put together from the information that has come forward in the
mailing list which is very active in reporting bugs.

   How stable is *MySQL*? Can I depend on *MySQL* in this project!

   This is about the 3.21.x version of *MySQL*. All known and reported
bugs are fixed in the latest version with the exception of the bugs
listed in the BUGS file which are things that are 'design' related.

   *MySQL* is written in multiple layers and different independent
modules. Here is a list of the different modules and how tested each of
them are.

*The ISAM table handler. Stable*
     This is how all the data is stored. In all *MySQL* releases there
     hasn't been a single (reported) bug in this code. The only known
     way to get a corrupted table is to kill the server in the middle
     of a update and because all data is flushed to disk between each
     query even this is unlikely to destroy any data beyond rescue.
     There hasn't been a single bug report about lost data because of
     bugs in *MySQL* either.

*The parser and lexical analyser. Stable*
     There hasn't been a single reported bug in this system for a
     couple of months.

*The C client code. Stable*
     No known problems. In early 3.20 releases there were some
     limitations in the send/receive buffer size. In 3.21.x the
     send/receive buffer is now dynamic up to a default of 512K.

*mysql, mysqladmin and mysqlshow. Stable*
     The command line clients have had very few bugs.

*mysqldump and mysqlimport. Beta*
     Rewritten for 3.21.

*Basic SQL. Stable*
     The basic SQL function system and string classes and dynamic memory
     handling. Not a single reported bug on this system.

*Query optimiser. Gamma*
     Some changes in 3.21.

*Range optimiser. Alpha*
     Totally rewritten for 3.21.x

*Join optimiser. Gamma*
     Small changes for 3.21.

*GROUP BY, ORDER BY and related function COUNT(). Beta*
     Rewritten for 3.21 and throughly tested.

*Locking. Gamma*
     This is very system dependent. One some systems there are big
     problems using standard OS locking (fcntl).  In these cases, you
     should run the *MySQL* daemon with the `--skip-locking' flag.
     Known problems are some Linux systems and SUNOS when using NFS
     mounted file systems.

*Linux threads. Gamma*
     The only found problem is with the fcntl() call, which is fixed by
     using -skip-locking. Some people have reported lockup problems
     with the 0.5 release.

*Solaris 2.5+ pthreads. Stable*
     We use this for all our production work.

*MIT threads (Other systems). Beta*
     No reported bugs since 3.20.15 and no known bugs since 3.20.16. On
     some system there is 'misfeature' where some operations are quote
     slow (a 1/20 second sleep is done between each query). Of course
     MIT threads may slow down everything a bit, but for index based
     selects a select is usually done in one time frame so there
     shouldn't be a mutex locking/thread juggling.

*Other thread implementions. Alpha*
     The ports to other systems is very new and may still have bugs,
     either in *MySQL* or most often in the thread implementation
     itself.

*LOAD DATA..., INSERT ... SELECT. Stable*
     Some people have thought they have found bugs in this but has
     turned up being misunderstandings. So check the manual before
     reporting bugs!

*ALTER TABLE. Gamma*
     Partly rewritten for 3.21.

*mysqlperl. Stable*
     No bugs reported except a lot of compiling and linking problems.

*DBD. Beta*
     Now maintained by Jochen Wiedmann.  <<wiedmann@neckar-alb.de>>.
     Thanks!

*mysqlaccess. Beta*
     Written and maintained by <Yves.Carlier@rug.ac.be>. Thanks!

*The Technical Documentation. Beta*
     It is improving.

*MyODBC (uses ODBC SDK 2.5). Beta*
     It seams to work well with some programs.

   TcX provides email support for paying customers, but the *MySQL*
mailing list usually provides answers to all common questions. Bugs are
usually fixed right away with a patch that usually works and for
serious bugs there is almost always a new release.

Why are there is so many releases of *MySQL*?
=============================================

   Well, *MySQL* is evolving quite rapidly here at TcX and we want to
share this with other *MySQL* users. We try to make a release when we
have a very useful feature that others seem to have a need for.

   We also try to help out users who request features that are easy to
implement. We also take note on what our licensed users want to have and
we especially take notes on what our extended email supported customers
want and try to help them out.

   No one has to download a new release. The News section will tell you
if the new release has something you really want. *Note News::.

   If there is, by any chance, a fatal bug in a release we will make a
new release as soon as possible, that fixes the problem. We would like
other companies to do this too :)

   The 3.21.x version has had many big changes for portability to a lot
of different systems. When the 3.21 release is stable we will remove the
alpha/beta suffix and move active development to the 3.22. Bugs will
still be fixed in the stable version. We don't believe in a complete
freeze, as this also leaves out bug fixes and things that 'must be
done'. 'Somewhat freezed' means that we will maybe add small things that
'almost surely will not affect anything thats already working'.

   If you are running and old system and want to upgrade, but you don't
want to take chances with 3.21 you should upgrade to 3.20.32.  I have
tried to only fix fatal bugs and small, relatively safe changes in this
version.

   If you are trying *MySQL* for the first time or have a little time
to test out that your current system, you should use 3.21.

Checking a table for errors.
============================

   If *MySQL* crashed (for example if the computer is turned off) when
all data is not written to disk the tables may have become corrupted. To
check a table use:

`isamchk table_name'
     This finds 99.99 % of all errors. What it can't find is when only
     the data file has been corrupted.

`isamchk -e table_name'
     This goes through all data and does a complete check.

`isamchk -ei table_name'
     As the above but it also prints some statistics.

   We at TcX run a cron job on all our important tables once a week.

     35 0 * * 0 /path/to/isamchk -s /path/to/dbs/*/*.ISM

   This prints out any crashed tables so we can go and examine and
repair them when needed.

   As we haven't had any unexpected crashed (without hardware trouble)
tables for a couple of years now (this is really true), once a week is
more than enough of us.

   Of course, whenever the machine has done a reboot in the middle of a
update one usually has to check all the tables that could have been
affected. (This is a 'expected crashed table')

   We recommend that to start with one should do a `isamchk -s' on all
updated tables each night until one gets to trust *MySQL* as much as we
trust it.

   Naturally, one could add a check to safe_mysql that, if there is an
old pid file left after a reboot, it should check all tables that have
been modified the last 24 hours.

How to repair tables.
=====================

   The file format that *MySQL* uses to store data has been extensively
tested, but there is always instances (like a hard kill on the mysqld
process in the middle of a write, a hardware error or a unexpected
shutdown of the computer) when some tables may be corrupted.

   The sign of a corrupted table is usually when queries abort
unexpectedly and one gets errors like:

   * table.frm is locked against change.

   * Can't find file 'table.ISM' (Errcode: ###)

   * Got error ### from table handler. (Error 135 is an exception in
     this case)

   * Unexpected end of file.

   * Record file is crashed.

   In thess cases you have to repair your tables. The isamchk extern
utility can usually detect and fix most things that can go wrong. *Note
isamchk::.

   If you are going to use isamchk on very large files, you should first
decide how much memory you want to give to isamchk. More memory gives
more speed. For example, if you have more than 32M ram, try:

     isamchk -O sortbuffer=16M -O keybuffer=16M -O readbuffer=1M
             -O writebuffer=1M ....

   * Part 1: Checking
        * Check the permissions of the table files. Make them readable
          for the user running mysqld.

        * cd to the database directory.

        * Run 'isamchk *.ISM' or ('isamchk -e *.ISM' if you have more
          time).

        * You only have to repair those tables that your isamchk gives
          an error. Use option -s to avoid unnecessary information.

   * Part 2: Easy safe repair.
        * If you get weird errors when checking or repairing, like out
          of memory or if isamchk crashes, go to part 3.

        * Try first 'isamchk -rq table'. This will try to repair the
          .ISM file without touching the important data table (.ISD).
          If the data file (.ISD) contains everything and the delete
          links point at the right places in the data file, this should
          work and the table is fixed. Start repairing next table.

        * Make a backup of the data file (table.ISD) before continuing.

        * Use 'isamchk -r table'. This will remove wrong records and
          deleted records from the data file and reconstruct the index
          (.ISM) file.

        * If the above fails, use 'isamchk -ro table'. This is a little
          slower but a crash-safer version of the above.

   * Part 3:; Hard repair.
        * This should only happen if the first 16K block in the .ISM
          file is destroyed, contains wrong information or if the .ISM
          is missing.

        * In this case we have to create a new .ISM file. Do as follows:

        * Move the data file .ISD file to some safe place.

        * Recreate the .ISM file from the .frm file:
               shell> mysql database
               mysql> delete from table_name;
               mysql> quite

        * Copy (don't move) the data file (.ISD) back on the newly
          created .ISD file

        * Go back to Part 2. (This shouldn't be a endless loop).
          isamchk -rq should now work.

   * Part 4: Very hard repair.
          This can only happen if the descriptor file (.frm) also has
          crashed. This should never happen, because the .frm file
          isn't written to after the table is created.

        * Restore the .frm file from a backup and go back to Part 3.
          You can also restore the .ISM file and go back to Part 2.  In
          the latter case you should start with 'isamchk -r'.

        * If you don't have a backup but know exactly how the table was
          created, create a copy of the table in another database and
          copy the .frm and .ISM file from there to your crashed
          database and go back to Part 2.

Is there anything special to do when upgrading/downgrading *MySQL*?
===================================================================

   One can always move the *MySQL* form and data files between
different versions on the same architecture as long as one has the same
base version of *MySQL*. The current base version is of course 3. If
one changes the character set (sort order) by recompiling *MySQL* one
has to do a `isamchk -rq' on all tables.

Upgrading to 3.21 from a 3.20 version
-------------------------------------

   If you already have a version older than 3.20.28 running and want to
switch to 3.21.# you have to do the following:

   You can start the `mysqld' 3.21 server with `safe_mysqld
--old-protocol' to use it with the original 3.20 data. In this case the
new client function, `mysql_errno()', will not return any server error,
only `CR_UNKNOWN_ERROR', (but it works for client errors) and the
server uses the old password() checking instead of the new one.

   If you are *NOT* using `--old-protocol':

   * All client code must be recompiled. If you are using ODBC you must
     get the new myodbc 2.# driver

   * The script `scripts/add_long_password' must be run to convert the
     password field in the 'mysql/user' table to `char(16)'.

   * All passwords must be reassigned in the mysql/user table (to get 62
     instead of 31 bit passwords).

   * The table format hasn't changed so you don't have to convert any
     tables.

   *MySQL* 3.20.28 and above can handle the new user table format
without affecting clients. If you have a *MySQL* version below 3.20.28,
passwords will not work on it anymore if you convert the user table. So
to be safe, you should first upgrade to at least 3.20.28 and then
upgrade to 3.21.#.

   The new client code works with a 3.20.# version, so you can use the
old 3.20.# server if you experience problems with 3.21.# without having
to recompile the clients again.

   If you are not using the option `--old-protocol' to `mysqld', old
clients will issue the error message:

   `ERROR: Protocol mismatch. Server Version = 10 Client Version = 9'

*MySQL* Server functions
************************

Which languages are supported by *MySQL*?
=========================================

   `mysqld' can give error messages in the following languages: Czech,
Dutch, English (default), French, German, Norwegian, Norwegian-ny,
Polish, Portuguese, Spanish and Swedish.

   To start `mysqld' with a language use one of the `--language=lang'
or `-L lang' switches:

   `mysqld --language=swedish' or `mysqld
--language=/usr/local/share/swedish'

   Note that all the language names are in lowercase.

   The language files are located in `MYSQL_BASE_DIR/share/LANGUAGE/'.

Character set used for data & sorting.
--------------------------------------

   By default *MySQL* will use the ISO8859-1 (Latin1) character set.
This is the character set used in the USA and western Europe.

   The character set decides what characters are allowed in names and
how things are sorted by the `ORDER BY' and `GROUP BY' commands.

   You may change this at compile time by the configure switch
`--with-charset=charset'. *Note Quick-install::.

The Update log
==============

   When started with the `--log-update=file_name' switch `mysqld' makes
a log file with all SQL command that update data. It results in a file
with name of `file_name.#' where # is a number that is increased for
each reload. If you do not give a file name the current hostname is
used.

   The log in smart since it only writes statements that really update
data. So a `UPDATE' or a `DELETE' with a where that find no rows is not
written to the log. It even skips `UPDATE's that update a column to the
value it had before.

   The current limitations of `--log-update' are:

   `TIMESTAMP' and all other updates with time functions will get the
current date instead of the orignal date.

   `LAST_INSERT_ID()' values should be logged for more safety.

How big can *MySQL* tables be.
==============================

   Currently a table is limited to the operation system file size.  On
Linux the current limit is 2G, on Solaris 2.5.1 the limit is 4G and on
Solaris 2.6 the limit is going to be 1000G. To get more that 4G requires
some changes to *MySQL* that are on the Todo. *Note Todo::.

   If your big table is going to be read_only, you could use pack_isam
(*Note pack_isam::) to merge and compress many tables to one.  As
pack_isam usually compresses a table with at least 50% you can have much
bigger tables.

   Another solution can be included MERGE library allows one to handle a
collection of identical tables as one. Currently MERGE can only be used
to scan a collection of tables because it doesn't support indexes. We
will add indexes on this in the near future.  Identical in this case
means that all tables are created with identical column information.

Solving some common problems with *MySQL*
*****************************************

Database replication
====================

   The most general way to do database replication is using the update
log. *Note Update log::. This requires that one database acts as a
master (all data changes are done here) and one or more others as
slaves. To update a slave just run `mysql < update_log'.

   If you never do deletes you can use timestamps.

   It is possible to make a two way updating system using both the
update log (for deletes) and timestamps (on both sides). But in that
case you must be able to handle confilics when the same data has been
changed in both ends. You probably want to keep the old version to help
with deciding what has been updated.

Backup of databases
===================

   Since *MySQL* tables are stored as files it is easy to do a backup.
To get a consistent backu do a `LOCK TABLES' on the relevant tables.
*Note Lock tables::. You only need a read lock so other threads can
continue to query the tables. When make a copy of the files in the
database directory. Or if you want to make a sql level backup you can
use `SELECT INTO OUTFILE'.

   Another way is to use the `mysqldump' script.

     Do a full backup of your databases, with `mysqldump --tab=some-dir
     --lock-tables' or simply by copying all table files (.frm, .ISM and
     .ISD) away while the server isn't updating anything.

   * start `mysqld' with `--log-update'

   * You will get log files with name of 'hostname'.# where # is a
     number that is increased for each reload.

   When you have to restore something (if `isamchk -r' can't restore
all data as it can in 99.9% of all cases):

   * Restore the original mysqldump backup.

   * ls -1 -t -r hostname.* | xargs cat | mysql

   The ls in the last command is done to get all log files in the right
order

   You can also do selective backups with `select * into outfile from
table' and restore with ` LOAD DATA FROM INFILE 'file_name' REPLACE
...'. To avoid dublicate recods you need a `PRIMARY KEY' in the table.
The `REPLACE' means that if there is a 'duplicate index' conflict when
inserting new records the old record will be replaced with the new one.

How to get maximum performance out of *MySQL*
*********************************************

How does one change the size of *MySQL* buffers?
================================================

   You can get the currently used buffer sizes with:

   > `./mysqld --help'

   This should result in a list of all mysqld options and configurable
variables like the following.

     Possibly variables to option --set-variable (-O) are:
     back_log              current value: 5
     join_buffer           current value: 131072
     key_buffer            current value: 1048568
     max_allowed_packet    current value: 65536
     max_connections       current value: 90
     max_join_size         current value: 4294967295
     max_sort_length       current value: 1024
     net_buffer_length     current value: 8192
     record_buffer         current value: 131072
     sort_buffer           current value: 2097144
     table_cache           current value: 64
     tmp_table_size        current value: 1048576
     thread_stack          current value: 65536

back_log                How many outstanding connection requests may      
                       *MySQL* have. This comes into play when the main   
                       *MySQL* thread gets *VERY* many connection         
                       requests in a very short time. It when takes some  
                       time (but very short) for the main thread to       
                       check the connection and start a new thread. The   
                       back_log is how many connects can be stacked       
                       during this short time before *MySQL* momentarily  
                       stops answering new requests. You only need to     
                       increase this is you expext a large number of      
                       connections in a short period of time.             
                                                                          
                          Or in other words the size of the listen queue  
                       for incoming tcp/ip connections.  The manual page  
                       for the unix system call listen(2) should have     
                       more details.                                      
                                                                          
                          Check your OS documentation for the maximum     
                       value for this value.                              
join_buffer             This buffer is used for full joins (without       
                       indexs). It is allocated one time for each full    
                       join between two tables. Increase this to get a    
                       faster full join when adding indexes is not        
                       possible. Normaly the best way to get fast joins   
                       is adding indexes.                                 
key_buffer              Buffers index blocks and is shared by all         
                       threads. You might want to increase this when      
                       doing many delete/inserts on a table with lots of  
                       indexs. To get even more speed use `LOCK TABLES'.  
                       *Note Lock tables::.                               
max_allowed_packet      Max size of one packet. This allows the message   
                       buffer to grow up to this limit when needed (it    
                       is initiated to `net_buffer_length'). May be set   
                       very big because this is mainly to find erroneous  
                       packets. You must increase this if you are using   
                       big BLOBS. It should be as big as the biggest      
                       BLOB you want to use.                              
max_connections         How many simultaneous clients is allowed. If you  
                       increase this you probably has to increase the     
                       number of file descriptors mysqld has. This is     
                       Operating system depended so look at you OS        
                       documentation.                                     
max_join_size           Joins that touches more records that this return  
                       an error. Set this if you have users to tend to    
                       make joins without a where that take a long time   
                       and returns millions of rows.                      
max_sort_length         The number of bytes to use when sorting on        
                       `BLOB' or `TEXT' columns.                          
net_buffer_length       The communication buffer is reset to this size    
                       between each query. This should normally not be    
                       changed but if you have very little memory you     
                       can set it to the expected size of a query.        
record_buffer           Each thread that is doing a sequential scan       
                       allocats a buffer of this size for each table it   
                       scans. If you do many sequential scans you may     
                       want to increase this.                             
sort_buffer             Each tread that needs to do a sort allocats a     
                       buffer of this size. Increase this for faster      
                       `ORDER BY' or `GROUP BY'. A sort also allocates    
                       one or two temporary files. The maximum disk-space 
                       needed is `(length_of_what_is_sorted +             
                       sizeof(database_pointer)) * number_of_rows * 2'.   
                       `sizeof(database_pointer)' is usally 4 but may     
                       grow in the future for really big tables.          
table_cache             Number of open tables for all threads. If this    
                       is increased you must see to that the number of    
                       open file descriptor is also increased. *MySQL*    
                       need 2 file descriptors for each unique table.     
tmp_table_size          If a temporary table gets bigger than this a      
                       `The table ### is full' error will ge generated.   
                       Increase this if you do many advanced `GROUP BY'   
                       queries.                                           
thread_stack            How big will each threads `C' stack be. A lot of  
                       the limits detected by crash-me is dependent on    
                       this. The default is normally enough.              

   *MySQL* uses algorithms that are very scalable so one can usually
run with very little memory or give *MySQL* much memory to get a better
performance.

   If you have much memory and many tables and want to have maximum
performance with a moderate number of clients you should use something
like:
     > safe_mysqld -O key_buffer=16Mk -O table_cache=128 \
             -O sort_buffer=4M -O record_buffer=1M &

   If you have little memory with lots of connections, use something
like:
     > safe_mysqld -O key_buffer=512k -O sort_buffer=100k -O record_buffer=100k &

   or even

     > safe_mysqld -O key_buffer=512k -O sort_buffer=16k -O table_cache=32 \
             -O record_buffer=8k -O net_buffer=1K &

   Note that if you change a option to `mysqld' it is only for that
instance. To see the effects of a parameter change do something like
this `mysqld -O keybuffer=32m --help'.

   If there are very many connections, 'swapping problems' may occur if
mysqld has not been configured to use very little memory for each
connection. It also works nice if you have a enough memory for all
connections of course.

   For example, for 200 open connections one should have a table cache
of at least 200 * (max_number of tables in join).

How does *MySQL* use memory ?
=============================

   * The key_buffer is shared by all threads, the rest are allocated
     when needed.

   * Each connection uses some thread space, a stack (64K) and a
     connection buffer (variable `net_buffer_length').

   * All threads share the same base memory.

   * Nothing is memmapped yet (except compressed tables but that's
     another story). This is because 32bit memory space of 4GB is not
     large enough for most large tables. When we get a system with 64
     bit address space we may add general support for memmaping.

   * When starting `mysqld' one can specify a key buffer. This will
     buffer all indexs in all tables at FIFO basis (variable keybuffer).

   * Each request doing a sequential scan over a table allocates a read
     buffer (variable record_buffer).

   * Each request doing a sort, allocates a sortbuffer and one or two
     temporary files. The maximum extra disk-space needed is
     (sort_key_length +sizeof(long))*2.

   * All joins are done in one pass and most joins can be done without
     even using a temporary table. Most temporary tables are memory
     based (HEAP) tables. Temporary tables with a big recordlength (=
     sum of all column lengths) or that contains `BLOB's are stored on
     disk.  One current problem is that if the HEAP table exceeds the
     size of `tmp_table_size', one will get the error: 'The table ###
     is full'.  In the future we will fix this by automatically
     changing the in memory (HEAP) table to a disk based (NISAM) table
     if needed.  To go around this problem one can increase the `-O
     tmp_table_size=#' option to mysqld or use the SQL option
     `SQL_BIG_TABLES'.  *Note Set option::.  In *MySQL* `3.20' the
     maximum size of the temporary table was `recordbuffer*16', so if
     you are using this version you have to increase `recordbuffer'.
     There also exists a patch to always store temporary tables on
     disk, but this will affect the speed of all complicated queries.

   * Almost all memory used when parsing and calculating is done on a
     local memory store. No memory overhead is needed for small items
     and the normal slow memory allocation/freeing is avoided. Memory
     is only allocated for unexpectedly large strings (this is done
     with malloc/free).

   * Each index file is opened once and the data file is opened once
     for each concurrently running thread. For each concurrent thread a
     table structure, column structures for each column and a buffer
     that has the size of 3 * (maximum row length not counting BLOBS)
     is allocated. A BLOB uses 5 to 8 bytes +length of blob data.

   * For each table having BLOBS, a buffer is enlarged dynamically to
     read in larger BLOB's. If one scans a table there will be a
     allocated buffer as large as the largest BLOB.

   * All used tables are saved in a cache and used by FIFO. Normally
     the cache is 64 tables. If a table has been used by 2 running
     threads at the same time, there will be 2 entries of the table in
     the cache.

   * A `mysqladmin refresh' closes all tables that are not used and
     marks all used tables to be closed when the running thread
     finishes. This will effectively free most used memory.

   When running `mysqld' ps, other programs may report that is takes a
lot of memory. This may be caused by thread-stacks on different memory
addresses. For example, the Solaris ps calculates the unused memory
between stacks as used memory. You can verify this by checking available
swap with 'swap -s'. We have tested `mysqld' with commercial
memory-leakage detectors so there should not be any memory leaks.

How does *MySQL* use indexs?
============================

   All indexs, PRIMARY, UNIQUE and INDEX(), are stored in B trees.
Strings are automatically prefix- and end-space compressed.

   INDEX(col1, col2) creates a multiple index over the two columns.
The index can be seen like a concatenation of the given columns.  If
you use INDEX(col1), INDEX(col2) instead of INDEX(col1,col2) you get
two separate indexs instead.

     SELECT * FROM table WHERE col1=# AND col2=#

   In a case of INDEX(col1,col2) the right row(s) can be fetched
directly.  In a case of INDEX(col1), INDEX(col2) the optimiser decides
which index will find fewer rows and this index will be used to fetch
the rows.

   If the table has an index INDEX(col1,col2,col3...) the prefix of this
can be used by the optimiser to find the rows. This means that the above
gives you search capabilities on: INDEX(col1) and INDEX(col1,col2) and
INDEX(col1,col2,col3)...

   MySQL can't use a sub part of a index to locate rows through a index.

   With the definition INDEX(col1,col2,col3):

     SELECT * FROM table WHERE col1=#
     SELECT * FROM table WHERE col2=#
     SELECT * FROM table WHERE col2=# and col3=#

   only the first query will use indexs.

What kind of optimisation is done on the WHERE clause?
======================================================

   (Incomplete, *MySQL* does a lot of optimisations.)

   The first issue about getting a slow `SELECT ... WHERE' faster is to
check if one could add a index to make it faster. All references
between different tables should usually be done with indexs. One can use
the `EXPLAIN' command to check which indexes are used in a `select'.
*Note Explain::. *Note MySQL indexes::

   * Brace removal (all unnecessary braces are removed). `((a AND b)
     AND c OR (((a AND b) AND (c AND d))))' -> `(a AND b) OR (a AND b
     AND c AND d)'

   * Constant folding. `(a<b AND b=c) AND a=5' -> `b>5 AND b=c A=5'

   * Constant condition removal (needed because of constant folding).
     `(b>=5 AND b=5) OR (b=6 and 5=5) or (B=7 and 5=6)' -> `B=5 or B=6'

   * All constant expressions used by indexs are evaluated only once.

   * Return zero rows if impossible select.

   * HAVING is merged with WHERE if one doesn't use GROUP BY or group
     functions.

   * For each sub join a simpler WHERE is constructed to get a fast
     WHERE evaluation for each sub join and also to skip records as
     soon as possible.

   * Find all indexs that may be used. Use the index which finds least
     records. A index is used for the following cases: `=', `>', `>=',
     `<', `<=', `BETWEEN' and a `LIKE' with a character prefix like
     'something%'.

   * Remove indexs that don't span all `AND' levels.
        - have all preceding index_parts specified.

        - `index = 1 or A = 10' -> `NULL' (can't use index.)

        - `index = 1 or A = 10 and index=2' -> `index = 1 OR index = 2'

        - `index_part_1 = const and index_part_3 = const' ->
          `index_part_1 = const'

   * Read all constant tables. A constant table is:

       1. A table with 0 or 1 record.

       2. A table which uses only other const tables and constants on a
          full unique index.

          `const_table.index = constant'

        * `const_table.index_part_1 = const_table2.column and
          const_table.index_part_2 = constant'

   * Find the best join combination to join the tables, by trying all
     possibilities :(. If all columns in `ORDER BY' and in `GROUP'
     comes from the same table, then this table is preferred first when
     joining.

   * If there is a order clause and a different group clause or if the
     order or group contains columns from other tables than the first
     table in the join cue, a temporary table is created.

   * For each table use a ranged index, if possible, to read records.
     Each table index is queried and if there exists a index range that
     spans < 30% of the records then a index is used. If no such index
     can be found a quick table scan is used.

   * Before each record is output-ed, skip those that match the HAVING
     clause.

How does *MySQL* open & close tables?
=====================================

   The cache of open tables can grow to a maximum of `table-cache'
(default 64, changeable with -O table_cache=#).  A table is never
closed, except when the cache is full and another thread tries to open
a table or if one uses 'mysqladmin refresh'.

   When the limit is reached, *MySQL* closes as many tables as possible,
until the cache size has been reached or there are no more unused
tables.  This means that if all tables are in use by some threads,
there will be more open tables than the cache limit, but the extra
tables will be closed eventually.  Tables are closed according to
last-used order.

   A table is opened (again) for each concurrent access. This means that
if one has two threads running on the same table or access the table
twice in the same query (with AS) the table needs to be opened twice.
The first open of any table takes 2 file descriptors, each following
use of the table takes only one file descriptor.

What are the drawbacks of creating possibly thousands of tables in a database?
..............................................................................

   Each table is actually 3 files.  If you have many files in a
directory open, close and create will be slow.  If you also do selects
on many different tables there will be a little overhead because when
the table cache is full for every table that has to be opened another
has to be closed. One can make the overhead smaller by making the table
cache larger.

How should I arrange my table to be as fast/small as possible?
==============================================================

   * Use `NOT NULL' if possible. It makes everything faster and you
     save 1 bit per column.

   * All columns have default values. Only insert when the default value
     isn't acceptable. You don't have to insert the columns of a
     timestamp or an autoincremented index in the insert statement.
     *Note mysql_insert_id::.

   * Use the smaller INT types if possible to get smaller tables. For
     example, `MEDIUMINT' is often better than `INT'.

   * If you don't have any `VARCHAR' columns, a fixed size record format
     will be used. This is much faster but may unfortunately waste some
     space. *Note Row format::.

   * To make *MySQL* optimise queries better, run `isamchk -a' on the
     table once it is loaded with relevant data. This updates a value
     for each index that tells how many rows that have the same value
     for this index in average. Of course, this is always 1 for unique
     indexes.

   * To sort an index and data according to an index use `isamchk -Sir1'
     (if you want so sort on index 1). If you have a unique index that
     you want to read all records from in numeric order this is a good
     way to make that faster.

   * When loading a table with data use `LOAD DATA FROM INFILE'. This is
     usually 20 times faster than using a lot of INSERTs. If the text
     file isn't on the server, rcp it to the server first. *Note Load::.

     You can even get more speed when loading data to tables with many
     indexs by doing:
        * Create the table in mysql or perl with CREATE TABLE...

        * Do `mysqladmin refresh'.

        * Use `isamchk -k0 database/table_name'. This will remove all
          use of indexs from the table.

        * Insert data into the table with `LOAD DATA INFILE...'.

        * If you have pack_isam and want to compress the table, run
          pack_isam on it.

        * Recreate the indexs with `isamchk -rq database/table_name'.

        * Do `mysqladmin refresh'.

     The other possibility to get some more speed to both `LOAD DATA
     FROM INFILE' and `INSERT' is to enlarge the key buffer.  This can
     be done with the `-O key_buffer=#' option to `(safe)mysqld'.  For
     example 16M should be a good value if you have much RAM :)

   * When dumping data as textfiles to other programs, use `SELECT ...
     INTO OUTFILE'. *Note Load::.

   * When doing many inserts/updates in a row, you can get more speed
     by using `LOCK TABLES' on the tables. `...FROM INFILE...' and
     `...INTO OUTFILE...' are atomic so you don't have to use `LOCK
     TABLES' when using these. *Note Lock tables::.

   To check how you are doing, run `isamchk -evi' on the .ISM file.

What affects the speed of the INSERT statement?
===============================================

   The time to insert a record consists of:

   * Connect:                 (3)

   * Sending query to server: (2)

   * Parsing query:           (2)

   * Inserting record:        (1 x size of record)

   * Inserting indexs:          (1 x indexs)

   * Close:                   (1)

   Where (number) is proportional time. This does not take into
calculation the initial overhead to open tables (which is done once for
each simultaneous running query).

   The size of the table slows down the insert of indexs with N log N
(B-trees).

   A way of speeding ut inserts in to lock your table during the
inserts.

     LOCK TABLES a WRITE;
     
     INSERT INTO a VALUES (1,23)
     INSERT INTO a VALUES (2,34)
     INSERT INTO a VALUES (4,33)
     INSERT INTO a VALUES (8,26)
     INSERT INTO a VALUES (6,29)
     
     UNLOCK TABLES;

   The main speed difference is that the index buffer is only flushed
once to disk for all inserts. Normally there would be as many index
buffer flushes as there are inserts.

   Locking will also lower the total time of multi-connection test but
the maximum wait time for some threads will go up.

   For example:

     thread 1 does 1000 inserts
     thread 2, 3, and 4 does 1 insert
     thread 5 does 1000 inserts

   If you don't use locking, 2, 3 and 4 will finish before 1 and 5. If
you use locking 2,3,4 may finnish before 1 or 5 but probably not, but
the total time should be about 40 % faster.

   As `INSERTS', `UPDATES' and `DELETES' are very fast in *MySQL* one
will get better overall performance by adding locks around everything
that does more than about 5 inserts/updates in a row.  If one does very
many inserts in a row one could do a `UNLOCK TABLES' followed by a
`LOCK TABLES' once in a while (about each 1000 rows) to give other
threads access to the table. This would still give a nice performance
gain.

   Of course `LOAD DATA INFILE' is much faster still.

What affects the speed of DELETE statement?
===========================================

   The delete time of a record is exactly proportional to the number of
indexs. To increase the speed of deletes you can increase the size of
the index cache. The default index cache is 1M and to get faster
deletes it should be increased a couple of times (try 16M if you have
enough memory).

How do I get *MySQL* to run at full speed?
==========================================

   * Start `mysqld' with the right options. More memory gives more speed
     if you have it. *Note MySQL parameters::.

   * Create indexs to get your `SELECT''s faster. *Note MySQL indexes::

   * Optimize your column types to be as efficient as possible. Use
     `NOT NULL' on all columns.  *Note Table efficiency::

   * `--skip-locking' disables file locking between SQL requests. This
     gives a greater speed but has the following consequences:
        * One *MUST* flush all tables with `mysqladmin refresh' before
          one tries to check/repair tables with `isamchk'. (`isamchk -d
          table_name' is always allowed).

        * One can't run two *MySQL* servers one the same data files, if
          both are going to update the same tables.  The
     `--skip-locking' is default when compiling with MIT threads.  This
     is because flock() isn't fully support by MIT threads on all
     platforms.

   * If updates are a problem, updates can be delayed and then do many
     updates in a row later. Many updates done in a row are much
     quicker than one at a time.

   * If the problem is with MIT threads and one is using FreeBSD x.x.
     upgrading to FreeBSD 3.0.(or higher:) should help. This gives a
     possibility to use sockets (quicker than the current TCP/IP with
     MIT threads) and the thread package is much more integrated.

What are the different row formats? Or when to use VARCHAR/CHAR?
================================================================

   Actually using no `VARCHAR' or `BLOB' types results in a fixed row
size. Otherwise `CHAR' and `VARCHAR' are the same.

   You can check the format used in a table with `isamchk -d'.

   *MySQL* has three different table formats:

  1. Fixed length tables.
        * This is the default format.

        * All non packed columns are space filled.

        * Very quick.

        * Easy to cache.

        * Easy to reconstruct if crashed (of course, this only
          theoretical :-) as records are in fixed positions.

        * Don't have to be reorganised unless a huge number of records
          are deleted.

  2. Dynamic tables
        * Is used if there exists any columns with a `VARCHAR', `TEXT'
          or `BLOB' type in a table.

        * All strings are dynamic (except if length < 3).

        * Each record is preceded with a bitmap for which columns are
          not empty (this isn't the same as null columns).

        * Each string is saved with a length byte + string. If string
          is zero length or a number is zero it takes no extra space,
          just the zero length bit for each column.

        * Each record is uses the exact record space required. If a
          record becomes larger it is split into as many pieces as
          required.

        * Takes little disk space.

        * If records are changed a lot, `isamchk -r' should be run now
          and then to reorganise the table. This is to get a better
          layout. Use `isamchk -ei table_name' for some statistics.

        * Not as easy to reconstruct because a record may be in many
          pieces and a link may be missing.

        * The expected row length for dynamic sized records is: 3 +
          (number_of_columns + 7) / 8 + (number of char columns) +
          packed_size_of_number_columns + length_of_strings +
          (null_columns + 7) / 8. There will be a penalty of 6 bytes
          for each link. A dynamic record will be linked whenever a
          update causes a enlargement of the record. Each new link will
          be at least 20 bytes, so the next enlargement will probably
          go in the same link. If not, there will be another link. You
          may check how many links there are with `isamchk -ed'. All
          links may be removed with `isamchk -r'.

  3. Compressed tables (this is only with UNIREG/pack_isam)
        * Read only tables.

        * Takes very little disk space. Minimises disk usage.

        * Each record is compressed separately (very little access
          overhead).

        * Can handle fixed or dynamic length records, but no BLOBs.

        * Can be uncompressed with isamchk.

Why so many open tables?
========================

   When you run `mysqladmin status' you get something like:

     Uptime: 426 Running threads: 1 Questions: 11082 Reloads: 1 Open tables: 12

   This can be somewhat perplexing if you only have 6 tables.

   As *MySQL* is multithreaded it may have many queries on the same
table at once. To minimise the problem with two threads having
different states on the same file, I open the table again for each
concurrent thread. This takes some memory and one extra file descriptor
for the data file. The index file descriptor is shared all threads.

*MySQL* benchmark suite
***********************

   This should contains a technical describtion of the *MySQL*
benchmark suite (and crash-me) but that describtion is not written yet.
Currently see the code and results in `bench' directory in the
distribution. And of course on the web page (http://www.tcx.se/crash-me.html).

   It is meant to be a benchmark that will tell any user what things a
given SQL implementation is good or bad at.

   crash-me tries to find what a database supports by actually running
queries. It find for example:

   * What column types are supported.

   * How many indexes.

   * What functions are supported.

   * How big can a query be.

   * How big can a varchar column be.

*MySQL* Utilites
****************

Overview of the different *MySQL* programs
==========================================

   All *MySQL* clients that communicate with the server useing the
`mysqlclient' library use the following environment variables:

Name                   Description                                        
MYSQL_UNIX_PORT        The default socket. Used with 'localhost'.         
MYSQL_TCP_PORT         The default TCP port.                              
MYSQL_PWD              The default password.                              

`mysql'
     A SQL shell (with gnu readline). Supports interactive use or as a
     non interactive query tool. When used interactively result is
     given in a ascii-table format, but when used as a filter the
     result is a tab-separated output.

`mysqlaccess'
     Script to check the privileges for a host, user and database
     combination.

`mysqladmin'
     Administration utility. Create/Drop of databases, reload (read new
     users) and refresh (flush tables to disk, reopen log files). Also
     gives version and process info.

`mysqld'
     The SQL daemon. This should always be running.

`mysqldump'
     Dump a *MySQL* database into a file with SQL statements or tab
     separated text files. Enchanted freeware originally by Igor
     Romanenko.

`mysqlimport'
     Imports one or more text-files into respective tables. Can use all
     formats supported by `LOAD DATA INFILE'. *Note Load::

`mysqlshow'
     Shows information about database, tables, columns and indexs.

`mysqlbug'
     This script should always be used when filing a bug report to the
     *MySQL* list.

`mysql_install_db'
     Creates the *MySQL* grant tables with default privileges. This is
     usually only executed when installing the first *MySQL* release on
     a new system.

`isamchk'
     Check, optimise and repair *MySQL* tables.

`make_binary_release'
     Makes a binary release of a compiled *MySQL*. This could be sent
     by ftp to www.tcx.se/pub/mysql/Incoming for the convenience of
     other *MySQL* users.

`msql2mysql'
     A shell script to convert a `mSQL' program to *MySQL*. Doesn't
     handle all cases but gives a good start when converting.

`replace'
     Binary used for msql2mysql. Utility program to change strings in
     place in files or on stdin. Uses a finite state machine to match
     longer strings first. Can be used to swap strings, for example
     `replace a b b a -- files' swaps `a' and `b' in the given files.

`safe_mysqld'
     Starts the mysqld demon with some safety features. Restarts on
     error and has logging of runtime information to a log file.

The *MySQL* table check, optimize and repair program
====================================================

   For information about how to use isamchk to repair a crashed table:
*Note Repair::.

isamchk memory use
------------------

   `isamchk' doesn't use any more memory than you allow it to use with
the `-O' options. The default is to use only about 2M to fix things.

   But `isamchk' uses temporary files in `TMPDIR'. If `TMPDIR' points
to a memory file system you mey easily get out of memory errors.

   Using `-O sortbuffer=16M' should probably be enough for most cases.

Getting low level table information
-----------------------------------

   To get a description/statistics from a table use the forms below. We
will explain some of the information in more detail later.

`isamchk -d table_name'
     isamchk in 'describe mode'. If one uses `--skip-locking' `isamchk'
     may report an error for a table that is updated while isamchk
     runs, but there isn't any risk of destroying data.

`isamchk -d -v table_name'
     A little more verbose.

`isamchk -eis table_name'
     Shows only the most important information from a table. Slow since
     it must read the whole table.

`isamchk -eiv table_name'
     Same as above but tells you what it is being done.

   Example of `isamchk -d' output:
     ISAM file:     company.ISM
     Data records:           1403698  Deleted blocks:         0
     Recordlength:               226
     Record format: Fixed length
     
     table description:
     Key Start Len Index   Type
     1   2     8   unique  double
     2   15    10  multip. text packed stripped
     3   219   8   multip. double
     4   63    10  multip. text packed stripped
     5   167   2   multip. unsigned short
     6   177   4   multip. unsigned long
     7   155   4   multip. text
     8   138   4   multip. unsigned long
     9   177   4   multip. unsigned long
         193   1           text

   Example of `isamchk -d -v' output:
     ISAM file:     company.ISM
     Isam-version:  2
     Creation time: 1996-08-28 11:44:22
     Recover time:  1997-01-12 18:35:29
     Data records:           1403698  Deleted blocks:              0
     Datafile: Parts:        1403698  Deleted data:                0
     Datafilepointer (bytes):      3  Keyfile pointer (bytes):     3
     Max datafile length: 3791650815  Max keyfile length: 4294967294
     Recordlength:               226
     Record format: Fixed length
     r
     table description:
     Key Start Len Index   Type                      Root Blocksize Rec/key
     1   2     8   unique  double                15845376      1024       1
     2   15    10  multip. text packed stripped  25062400      1024       2
     3   219   8   multip. double                40907776      1024      73
     4   63    10  multip. text packed stripped  48097280      1024       5
     5   167   2   multip. unsigned short        55200768      1024    4840
     6   177   4   multip. unsigned long         65145856      1024    1346
     7   155   4   multip. text                  75090944      1024    4995
     8   138   4   multip. unsigned long         85036032      1024      87
     9   177   4   multip. unsigned long         96481280      1024     178
         193   1           text

   Example of `isamchk -eis' output:
     Checking ISAM file: company.ISM
     Key:  1:  Keyblocks used:  97%  Packed:    0%  Max levels:  4
     Key:  2:  Keyblocks used:  98%  Packed:   50%  Max levels:  4
     Key:  3:  Keyblocks used:  97%  Packed:    0%  Max levels:  4
     Key:  4:  Keyblocks used:  99%  Packed:   60%  Max levels:  3
     Key:  5:  Keyblocks used:  99%  Packed:    0%  Max levels:  3
     Key:  6:  Keyblocks used:  99%  Packed:    0%  Max levels:  3
     Key:  7:  Keyblocks used:  99%  Packed:    0%  Max levels:  3
     Key:  8:  Keyblocks used:  99%  Packed:    0%  Max levels:  3
     Key:  9:  Keyblocks used:  98%  Packed:    0%  Max levels:  4
     Total:    Keyblocks used:  98%  Packed:   17%
     
     Records:          1403698    M.recordlength:     226   Packed:             0%
     Recordspace used:     100%   Empty space:          0%  Blocks/Record:   1.00
     Recordblocks:     1403698    Deleteblocks:         0
     Recorddata:     317235748    Deleted data:         0
     Lost space:             0    Linkdata:             0
     
     User time 1626.51, System time 232.36
     Maximum resident set size 0, Integral resident set size 0
     Non physical pagefaults 0, Physical pagefaults 627, Swaps 0
     Blocks in 0 out 0, Messages in 0 out 0, Signals 0
     Voluntary contexts switches 639, Involuntary contexts switches 28966

   Example of `isamchk -eiv' output:
     Checking ISAM file: company.ISM
     Data records: 1403698   Deleted blocks:       0
     - check file-size
     - check delete-chain
     index  1:
     index  2:
     index  3:
     index  4:
     index  5:
     index  6:
     index  7:
     index  8:
     index  9:
     No recordlinks
     - check index reference
     - check data record references index: 1
     Key:  1:  Keyblocks used:  97%  Packed:    0%  Max levels:  4
     - check data record references index: 2
     Key:  2:  Keyblocks used:  98%  Packed:   50%  Max levels:  4
     - check data record references index: 3
     Key:  3:  Keyblocks used:  97%  Packed:    0%  Max levels:  4
     - check data record references index: 4
     Key:  4:  Keyblocks used:  99%  Packed:   60%  Max levels:  3
     - check data record references index: 5
     Key:  5:  Keyblocks used:  99%  Packed:    0%  Max levels:  3
     - check data record references index: 6
     Key:  6:  Keyblocks used:  99%  Packed:    0%  Max levels:  3
     - check data record references index: 7
     Key:  7:  Keyblocks used:  99%  Packed:    0%  Max levels:  3
     - check data record references index: 8
     Key:  8:  Keyblocks used:  99%  Packed:    0%  Max levels:  3
     - check data record references index: 9
     Key:  9:  Keyblocks used:  98%  Packed:    0%  Max levels:  4
     Total:    Keyblocks used:   9%  Packed:   17%
     
     - check records and index references
     [LOTS OF ROW NUMBERS DELETED]
     
     Records:          1403698    M.recordlength:     226   Packed:             0%
     Recordspace used:     100%   Empty space:          0%  Blocks/Record:   1.00
     Recordblocks:     1403698    Deleteblocks:         0
     Recorddata:     317235748    Deleted data:         0
     Lost space:             0    Linkdata:             0
     
     User time 1639.63, System time 251.61
     Maximum resident set size 0, Integral resident set size 0
     Non physical pagefaults 0, Physical pagefaults 10580, Swaps 0
     Blocks in 4 out 0, Messages in 0 out 0, Signals 0
     Voluntary contexts switches 10604, Involuntary contexts switches 122798

   Here is the data file sizes of the table used above.
     -rw-rw-r--   1 monty    tcx     317235748 Jan 12 17:30 company.ISD
     -rw-rw-r--   1 davida   tcx      96482304 Jan 12 18:35 company.ISM

   Explanations for the things `isamchk' prints:
`ISAM file'
     Name of isam file.

`Isam-version'
     Version of isam format. Currently always 2.

`Creation time'
     When was the data file created.

`Recover time'
     When was the index/data file last reconstructed.

`Data records'
     How many records/rows.

`Deleted blocks'
     How many deleted blocks still have reserved space. *Note Repair::.

`Datafile: Parts'
     For dynamic record format this shows how many data blocks there
     are. For a optimised table without splits this is the same as `Data
     records'.

`Deleted data'
     How many bytes of non reclaimed deleted data.

`Datafile pointer'
     How many bytes the datafile pointer has. It is usually 2, 3 or 4
     bytes. Most tables manage with 2 bytes but this cannot be
     controlled from *MySQL* yet. For fixed tables this is a record
     address. For dynamic tables this is a byte address.

`Keyfile pointer'
     How many bytes has the datafile pointer. It is usually 1, 2 or 3
     bytes. Most tables manage with 2 bytes but this is calculated
     automatically by *MySQL*. It is always a block address.

`Max datafile length'
     How long (in bytes) can the table's data file (`.ISD') get.

`Max keyfile length'
     How long (in bytes) can the table's key file (`.ISM') get.

`Recordlength'
     How much space does each record/row take.

`Record format'
     Which format does each record/row have. This example uses `Fixed
     length'.

`table description'
     A list of all keys in the table. For each key some low level
     information is presented.

`Key'
     This key's number.

`Start'
     Where in the record/row does this index-part start.

`Len'
     How long is this index-part. For packed numbers this should always
     be the full length of the column. For strings it may be shorter
     than the full length.

`Index'
     `unique' or `multip.'. If one value can exist multiple times in
     this index.

`Type'
     What data-type does this index part have. This is a `C' data-type
     with the options packed, stripped or empty.

`Root'
     Address of the root index block.

`Blocksize'
     The size of each index block. This is by default 1024 but may be
     changed a compile time.

`Rec/key'
     This is a statistical value used by the optimiser. It tells how
     many records there are per value for this key. A unique key always
     has a value of 1. This may be updated after a table is loaded (or
     greatly changed) with `isamchk -a'. If this is not updated at all,
     a default value of 30 is given.

`'
     The 9th key is a multiple part key with two parts.

`Keyblocks used'
     How many percent of the keyblocks are used. Since this table has
     just been reorganised with isamchk the values are very high (very
     near theoretical maximum).

`Packed'
     MySQL tries to pack keys with a common suffix. This can only be
     used for `CHAR'/`VARCHAR'/`DECIMAL' keys. For long strings like
     names, this can significantly reduce the space used. In the above
     example the 4 key is 10 characters long and gets a 60% reduction
     in space.

`Max levels'
     How deep is the btree for this key. Large tables with long keys
     get high values.

`Records'
     How many rows does the table have.

`M.recordlength'
     Average recordlength. For fixed tables this is the recordlength.

`Packed'
     MySQL strips spaces from the end of strings. How many percent did
     we save by doing this.

`Recordspace used'
     How many percent of the datafile is used.

`Empty space'
     How many percent of the datafile is unused.

`Blocks/Record'
     How many blocks are there per record. This is always 1 for fixed
     format tables. This value should stay as close to 1.0 as possible.
     If it gets to great you can reorganise the table with `isamchk'.
     *Note Repair::.

`Recordblocks'
     How many blocks are used. For fixed format, this is the same as
     the number of records.

`Deleteblocks'
     How many blocks are deleted.

`Recorddata'
     How many bytes of actual user data there are in the datafile.

`Deleted data'
     How many bytes of deleted data there are in the datafile.

`Lost space'
     If a record is updated to a shorter length some space is lost.
     This is the sum of all such losses.

`Linkdata'
     When the dynamic format is used, blocks are linked with pointers
     (length 4-7 bytes). This is the sum of all such pointers.

The *MySQL* compressed read only table generator
================================================

   `pack_isam' is an extra that you get when ordering more that 10
licenses or extended support. Since `pack_isam' is distributed binary
only, `pack_isam' is only available on some platforms.

   Of course, all future updates to `pack_isam' is included in the
price. `pack_isam' may at some time be included as standard when we get
some kind of turnover for *MySQL*.

   `pack_isam' works by compressing each column in the table
separately. The information needed to decompress is read into memory
when the table is opened. This gives a much better performance when
accessing individual records as one only has to uncompress exactly one
record, not a much larger disk block like when using stacker on MSDOS.

   MySQL uses memory mapping (mmap) on compressed tables and falls back
to normal read/write file usage if mmap did not work.

   Usually, pack_isam packs the datafile 40-70%.

   There is currently two limitations with pack_isam:
     After packing, the table is read only.

   * It can't pack blobs, yet.

   Fixing these limitations is on our TODO but with low priority.

   `pack_isam' options:

     > pack_isam --help
     pack_isam Ver 5.0 for SOLARIS 2.5 on SPARCstation
     Copyright (C) 1994-1997 TcX AB & Monty Program KB & Detron HB.
     This is not free software. You must have a license to use this program
     This software comes with ABSOLUTELY NO WARRANTY
     
     Pack a ISAM-database to take much smaller space
     Keys are not updated, one must run isamchk -rq on datafile afterwards
     Usage: pack_isam [OPTIONS]
     
       -b, --backup          Make a backup of the table as table_name.OLD
       -f, --force           Force packing of table even if it's gets bigger or
                             tempfile exists.
       -j, --join=#          Join all given tables into table.
                             All tables MUST be identical.
       -p, --packlength=#    Force storage size of recordlength (1,2 or 3)
       -s, --silent          Be more silent.
       -t, --test            Don't pack table only test packing it
       -v, --verbose         Write info about progress and packing result
       -w, --wait            Wait and retry if table is in use
       -T, --tmp_dir=#       Use temporary directory to store temporary table
       -#, --debug=...       output debug log. Often this is 'd:t:o,filename`
       -?, --help            display this help and exit
       -V, --version         output version information and exit

   Typical run:

     (/my/monty/tmp) ls -l station.*
     -rw-rw-r--   1 monty    my         994128 Apr 17 19:00 station.ISD
     -rw-rw-r--   1 monty    my          53248 Apr 17 19:00 station.ISM
     -rw-rw-r--   1 monty    my           5767 Apr 17 19:00 station.frm
     
     (/my/monty/tmp) isamchk -dvv station
     
     ISAM file:     station
     Isam-version:  2
     Creation time: 1996-03-13 10:08:58
     Recover time:  1997-02-02  3:06:43
     Data records:              1192  Deleted blocks:              0
     Datafile: Parts:           1192  Deleted data:                0
     Datafilepointer (bytes):      2  Keyfile pointer (bytes):     2
     Max datafile length:   54657023  Max keyfile length:   33554431
     Recordlength:               834
     Record format: Fixed length
     
     table description:
     Key Start Len Index   Type                       Root  Blocksize    Rec/key
     1   2     4   unique  unsigned long              1024       1024          1
     2   32    30  multip. text                      10240       1024          1
     
     column Start Length Type
     1     1     1
     2     2     4
     3     6     4
     4     10    1
     5     11    20
     6     31    1
     7     32    30
     8     62    35
     9     97    35
     10    132   35
     11    167   4
     12    171   16
     13    187   35
     14    222   4
     15    226   16
     16    242   20
     17    262   20
     18    282   20
     19    302   30
     20    332   4
     21    336   4
     22    340   1
     23    341   8
     24    349   8
     25    357   8
     26    365   2
     27    367   2
     28    369   4
     29    373   4
     30    377   1
     31    378   2
     32    380   8
     33    388   4
     34    392   4
     35    396   4
     36    400   4
     37    404   1
     38    405   4
     39    409   4
     40    413   4
     41    417   4
     42    421   4
     43    425   4
     44    429   20
     45    449   30
     46    479   1
     47    480   1
     48    481   79
     49    560   79
     50    639   79
     51    718   79
     52    797   8
     53    805   1
     54    806   1
     55    807   20
     56    827   4
     57    831   4
     
     Compressing station.ISD: (1192 records)
     - Calculating statistics
     
     normal:     20  empty-space:      16  empty-zero:        12  empty-fill:  11
     pre-space:   0  end-space:        12  intervall-fields:   5  zero:         7
     Original trees:  57  After join: 17
     - Compressing file
     87.14%
     
     (/my/monty/tmp) ls -l station.*
     -rw-rw-r--   1 monty    my         127874 Apr 17 19:00 station.ISD
     -rw-rw-r--   1 monty    my          55296 Apr 17 19:04 station.ISM
     -rw-rw-r--   1 monty    my           5767 Apr 17 19:00 station.frm
     
     (my/monty/tmp) isamchk -dvv station
     
     ISAM file:     station
     Isam-version:  2
     Creation time: 1996-03-13 10:08:58
     Recover time:  1997-04-17 19:04:26
     Data records:              1192  Deleted blocks:              0
     Datafile: Parts:           1192  Deleted data:                0
     Datafilepointer (bytes):      3  Keyfile pointer (bytes):     1
     Max datafile length:   16777215  Max keyfile length:     131071
     Recordlength:               834
     Record format: Compressed
     
     table description:
     Key Start Len Index   Type                       Root  Blocksize    Rec/key
     1   2     4   unique  unsigned long             10240       1024          1
     2   32    30  multip. text                      54272       1024          1
     
     Field Start Length Type                         Huff tree  Bits
     1     1     1      constant                             1     0
     2     2     4      zerofill(1)                          2     9
     3     6     4      no zeros, zerofill(1)                2     9
     4     10    1                                           3     9
     5     11    20     table-lockup                         4     0
     6     31    1                                           3     9
     7     32    30     no endspace, not_always              5     9
     8     62    35     no endspace, not_always, no empty    6     9
     9     97    35     no empty                             7     9
     10    132   35     no endspace, not_always, no empty    6     9
     11    167   4      zerofill(1)                          2     9
     12    171   16     no endspace, not_always, no empty    5     9
     13    187   35     no endspace, not_always, no empty    6     9
     14    222   4      zerofill(1)                          2     9
     15    226   16     no endspace, not_always, no empty    5     9
     16    242   20     no endspace, not_always              8     9
     17    262   20     no endspace, no empty                8     9
     18    282   20     no endspace, no empty                5     9
     19    302   30     no endspace, no empty                6     9
     20    332   4      allways zero                         2     9
     21    336   4      allways zero                         2     9
     22    340   1                                           3     9
     23    341   8      table-lockup                         9     0
     24    349   8      table-lockup                        10     0
     25    357   8      allways zero                         2     9
     26    365   2                                           2     9
     27    367   2      no zeros, zerofill(1)                2     9
     28    369   4      no zeros, zerofill(1)                2     9
     29    373   4      table-lockup                        11     0
     30    377   1                                           3     9
     31    378   2      no zeros, zerofill(1)                2     9
     32    380   8      no zeros                             2     9
     33    388   4      allways zero                         2     9
     34    392   4      table-lockup                        12     0
     35    396   4      no zeros, zerofill(1)               13     9
     36    400   4      no zeros, zerofill(1)                2     9
     37    404   1                                           2     9
     38    405   4      no zeros                             2     9
     39    409   4      allways zero                         2     9
     40    413   4      no zeros                             2     9
     41    417   4      allways zero                         2     9
     42    421   4      no zeros                             2     9
     43    425   4      allways zero                         2     9
     44    429   20     no empty                             3     9
     45    449   30     no empty                             3     9
     46    479   1                                          14     4
     47    480   1                                          14     4
     48    481   79     no endspace, no empty               15     9
     49    560   79     no empty                             2     9
     50    639   79     no empty                             2     9
     51    718   79     no endspace                         16     9
     52    797   8      no empty                             2     9
     53    805   1                                          17     1
     54    806   1                                           3     9
     55    807   20     no empty                             3     9
     56    827   4      no zeros, zerofill(2)                2     9
     57    831   4      no zeros, zerofill(1)                2     9

Adding functions to *MySQL*
***************************

Adding new functions to *MySQL*
===============================

   If you need it as sql function (like `SOUNDEX()'), its real easy:

  1. Add one line in `sql_lex.cc' defining the function name in the
     `sql_functions' array.

  2. Add two lines in `sql_yacc.y'. On defines the preprocessor symbol
     yacc can define (this should be added at the beginning of the
     file). Then define the function parameters and create an 'item'
     with these parameters.  Check, for example, all occurrences of
     SOUNDEX in `sql_yacc.y'

  3. In item_func.h declare a class inheriting from Item_num_func or
     Item_str_func depending on whether your function returns a number
     or a string.

  4. In `item_func.cc' add: `double *Item_func_newname::val()' If you
     are defining a number function or `String
     *Item_func_newname::Str(String *str)' if you are defining a string
     function.

  5. You should probably also define the following function: `void
     Item_func_newname::fix_length_and_dec()' This should at least
     calcutate `max_length' based on the given arguments. `max_length'
     is the maximal number of chars the function may return. If the
     function can't return a `NULL', one should set `maybe_null = 0'.

   About string functions:
  1. For string functions the `String *str' argument provides a string
     buffer that may be used to hold the result.

  2. A string function should return the string that holds the result.

  3. All current string functions tries to avoid to alloc any memory
     unless absolutely necessary!

ODBC
****

Which operating systems does *MySQL* ODBC support?
==================================================

   *MySQL* ODBC is a 32 bit ODBC (2.50) level 0 driver for Windows95
and NT. We hope somebody will port it to Windows 3.x.

How should I report problems with *MySQL* ODBC?
===============================================

   We have only tested ODBC with Admndemo, some C programs, Msquery and
Excel.

   To give some light about any problem we would like to have the log
file from the ODBC manager (the log you get when requesting logs from
ODBCADMIN) and a MYODBC log.

   To get a MYODBC log, please put this `MYSQL_DEBUG=d:t:O,filename' in
your `AUTOEXEC.BAT' and restart.

   The log will be written to file `filename'.

Programs known to work with MyODBC.
===================================

   Most programs should work with MyODBC, but these we tested ourselves
or got a confirmation from some user that is works:

Program
     Comment

Access
     To make Access work:
        * You should have a primary key in the table.

        * You should have a timestamp.

        * Only use double float fields. Access fails when comparing
          with single floats.

        * Set 2 in the options field when connection to *MySQL*.

Excel
     Works. Some tips
        * If you have problems with dates try to select them as strings.
               SELECT concat(sunrise_time), concat(sunset_time) FROM sunrise_sunset;
          Values returned in this format (string) should be correctly
          recognised by Excel97 as time values.

          What `concat()' does in this case is that it fools ODBC to
          think the column is of 'string type'. Without the 'concat()'
          ODBC knows the column is of time type. And Exel does not
          understand that.

          Note that this is uses bug in Excel because it automaticly
          converts a string to a time. This would be great if the
          source was a text file, but this is plain stupid when the
          source is a ODBC connection which reports exact types for
          each column.

odbcadmin
     Test program for ODBC.

Delphi
     One must use DBE 3.2 or newer.

C++Builder
     Tested with BDE 3.0. The only known problem is that when the table
     schema changes, query fields are not updated. BDE however does not
     seem to recognise primary keys, only the index PRIMARY, though
     this has not been a problem.

How do I fill in the various fields in the ODBC administrator program?
======================================================================

   There are three possibilities for specifying the server name on
windows95:

  1. Use the IP.

  2. Add a file lmhosts with the following info: `ip hostname' For
     example:
          194.216.84.21 my

  3. Configure the PC to use DNS.
        Example of how to fill in the 'ODBC setup'.
     Data Source Name:   test
     Description:        This is my test database
     Server:             194.216.84.21
     User:               monty
     Password:           my
     Port:

   These are default values to be given when prompting for a Driver
connect. You don't have to give 'server', 'user' or 'password' in this
screen. If port is not given the default port (3333) is used.

   When connection to a ODBC source you have the option to change the
server, user, password and port.

How to get the value of a AUTO_INCREMENT column in ODBC
=======================================================

   A common problem is how to get the value of a automatically
generated id from a insert. With ODBC you can do something like this:

     INSERT INTO foo (auto,text) VALUES(NULL,'text')
     select LAST_INSERT_ID()

   or if you are just going to insert in into another table:a

     INSERT INTO foo (auto,text) VALUES(NULL,'text')
     INSERT INTO foo2 (id,text) VALUES(LAST_INSERT_ID(),'text')

Problems and common errors
**************************

Some common errors when using *MySQL*
=====================================

`MySQL server has gone away' error.
-----------------------------------

   The most common reason for the `MySQL server has gone away' error is
that the server closed the connection because of a timeout. By default
the server closes the connection after 8 hours if nothing has happended.

   If you have a script you just have to reconnect and try again. If you
are using the mysql monitor just type `reconnect'.

Out of memory errors
--------------------

   If you do a query and get something like the following error:

     mysql: Out of memory at line 42, 'malloc.c'
     mysql: neaded 8136 byte (8k), memory in use: 12481367 bytes (12189k))
     ERROR 2008: MySQL client got out of memory

   Note that the error says the the *MySQL* client. The reason for this
error is simply that the client does not have enough memory to store
the whole result.

Packet to large
---------------

   When the client gets a block bigger that `net_buffer_length' it
issues a `Packet to large' error.

   If the `mysql' client is used you may set a bigger buffer by
starting the client with `mysql --set-variable= net_buffer_length=1m'.

The table is full
-----------------

   This error occurs when a in memory temporary table gets bigger than
`tmp_table_size'. To avoid this problem one can increase the `-O
tmp_table_size=#' option to mysqld or use the SQL option
`SQL_BIG_TABLES'. *Note Set option::.

How does *MySQL* hand a full disk
=================================

   On a disk full condition *MySQL* does the following:

     It checks once every minute if there is enough space to write the
     current row. If there is enough disk it continues as if nothing had
     happened.

   * Every 6 minutes it writes a entry to the log file warning about
     disk full.

   * To continue you have only to free enough free space to insert all
     records.

   * To abort you have to send a `mysqladmin kill' to the thread and
     free enough space for 1 row!

`Access denied?' error.
=======================

   *Note Privileges::. And especially *Note Access denied::.

How to run *MySQL* as a normal user.
====================================

   mysqld (the *MySQL* server) can run as any user. In order to change
mysqld to run as user USER, you'd have to the following:

   * Stop the server if it's running

   * Change the database directories so that USER has read and write
     privileges privileges to them: `shell> chown -R USER
     /your/path/to/mysql/var'

   * start the server as user USER

   * If you are using mysql.server to start mysqld when the system is
     rebooted, you should change mysql.server to call 'su' to user USER.

   *  You don't have to do anything to safe_mysqld to run as not root.

   At this point, your mysqld process would be running fine and dandy as
user 'USER'. One thing hasn't changed though - the access permissions.
By default (right after running the permissions table install script),
only user 'root' has access permission to the database.  Unless you
have changed that, it's still true. This shouldn't stop you from
accessing *MySQL* when you're logged in under a user other than root,
just specify -u root to the client program. Note that accessing *MySQL*
as root, by supplying -u root in the command line, doesn't have
ANYTHING to do with *MySQL* running as root, as a user or as anyone
else. The access permissions and userbase of *MySQL* are completely
separate from the UNIX users. The only connection to the UNIX users is
if you don't use the -u option to clients. In this case the client will
try to login into *MySQL* with your UNIX login name. If your UNIX box
itself isn't secured, you should probably at least put a password on
the root users in the *MySQL* access tables, since any johndoe user can
run 'mysql -u root dbname' and do whatever he likes.

Problems with file permissions
==============================

   If you have problems with file permissions, for example when
creating a table mysql gives: "ERROR: Can't find file:
'path/with/filename.frm' (Errcode: 13)", then you might have the wrong
value for environment variable UMASK.  Default umask is 0664. Fix:
     UMASK=432
     export UMASK
     ./bin/safe_mysqld

Problems using DATE columns.
============================

   The format of DATE is 'YYYY-MM-DD'. Actually nothing else is allowed
(ANSI SQL). One should use this format to update or in the WHERE clause,
ie select * from table_1 where idate >= '1997-05-05';

   As a convenience, *MySQL* automatically converts the date to a
number if used in a number context. It is also smart enough to allow a
'relaxed' string form when updating and in a `WHERE' with a compare to
a `TIMESTAMP', `DATE' or a `DATETIME' column.

   This means that the following works:

     insert into table_1 (idate) values (19970505) ;
     insert into table_1 (idate) values ('19970505') ;
     insert into table_1 (idate) values ('1997-05-05');
     insert into table_1 (idate) values ('1997.05.05');
     insert into table_1 (idate) values ('1997 05 05');
     
     select idate from table_1 where idate >= '1997-05-05';
     select idate from table_1 where idate >= 19970505;
     select mod(idate,100)1 from table_1 where idate >= 19970505;
     select idate from table_1 where idate >= '19970505';

   The following will not work:

     select idate from table_1 where strcmp(idate,'19970505')=0;
     Because '19970505' is compared as a string to '1997-05-05'.

Case sensitivity in searches.
=============================

   By default a *MySQL* column is case insensitive (There are some
character sets that never are case insensitive). That means that if you
search with `column like 'a%';' you will get all columns that start
with `A' or `a'. If you want to make this search case sensitive use
something like `INDEX(column, "A")=0' to check a prefix. Or
`STRCMP(column, "A") = 0' if the whole string should be the same.

   If you want `column' to always be treated in a case sensitive maner
declare it as `BINARY'. *Note Create table::.

   If you are using Chinese data in the so-called big5 encoding you
want to make all character columns `BINARY'. This works because the
sorting order of big5 encoding characters is based on the order of
ascii codes.

*MySQL* client tools and API's
******************************

*MySQL* C API
=============

   The `C' API is distributed with *MySQL*. It is included in the
`libmysqlclinet' library.It allows `C' programs to access a database.

   Most of the other client APIs (all except JAVA) use this library to
connect. So for example ypu can use the same environment variables.

   The client has a max communication buffer size. This is automatically
increase up to the maximum size (the default for this is 512kb). As
buffers are increased (but not decreased until close) on demand, it will
not take any resources if one increases this. This size check is mostly
a check for erroneous queries and communication packets.

   The commncation buffer must be big enough to contain a single SQL
statement and one row of returned data (but of course not at the same
time). Each threads communication buffer is dynamicly enlarged to handle
any row or query up to the imposed limit.

   So if you have `BLOB's that contains data up to 16M you must have at
least 16M as your communication buffer limit. *Note MySQL parameters::.

   MySQL shrinks each communication buffer to `net_buffer_length' after
each query.

*mysql_affected_rows*   Retrieves the number of affected rows by the      
                       last UPDATE, DELETE or INSERT.                     
*mysql_close*           Closes a server connection.                       
*mysql_connect*         Establish a connection to a *MySQL* server.       
*mysql_create_db*       Create a database.                                
*mysql_data_seek*       Seeks to an arbitrary row in a query result set.  
*mysql_drop_db*         Drop a database.                                  
*mysql_eof*             Determine if last row has been read.              
*mysql_error*           The error message from last *MySQL* function.     
*mysql_fetch_field*     Find out what type a table field is.              
*mysql_fetch_lengths*   Returns the length of all columns in a query      
                       result set.                                        
*mysql_fetch_row*       Fetch the 'next' row in the query result.         
*mysql_field_seek*      Put the column cursor on column number field.     
*mysql_free_result*     Free memory used to store a query result.         
*mysql_get_client_info* Return version information for the current        
                       client library.                                    
*mysql_get_host_info*   Returns name of server host.                      
*mysql_get_proto_info*  Get protocol version used by connection.          
*mysql_get_server_info* Returns the version number of the server.         
*mysql_insert_id*       Returns ID generated for a AUTO_INCREMENT field.  
*mysql_list_dbs*        Return maching database names.                    
*mysql_list_fields*     Return maching field names.                       
*mysql_list_processes*  Get a list of the current server threads.         
*mysql_list_tables*     Return maching table names.                       
*mysql_num_fields*      Return the number of columns in a result set.     
*mysql_num_rows*        Returns the number of rows in result set.         
*mysql_query*           Executes a SQL query.                             
*mysql_real_query*      Executes a SQL query with length information.     
*mysql_reload*          Reload the user permissions table in the server.  
*mysql_select_db*       Connect to a database.                            
*mysql_shutdown*        Shut down the database server.                    
*mysql_stat*            Return server status in a string.                 
*mysql_store_result*    Reads a result set to the client.                 
*mysql_use_result*      Initiate a dynamic result set for each row.       

`int *mysql_affected_rows*(MYSQL *mysql)'
     Retrieves the number of affected rows by the last UPDATE, DELETE
     or INSERT.

`void *mysql_close*(MYSQL *mysql)'
     Closes a server connection.

`MYSQL **mysql_connect*(MYSQL *mysql, const char *host, const char *user, const char *passwd)'
     Establish a connection to a *MySQL* server.

`int *mysql_create_db*(MYSQL *mysql, const char *db)'
     Create a database.

`void *mysql_data_seek*(MYSQL_RES *res, uint offset)'
     Seeks to an arbitrary row in a query result set.

`int *mysql_drop_db*(MYSQL *mysql, const char *db)'
     Drop a database.

`int *mysql_eof*(MYSQL_RES *)'
     Determine if last row has been read.

`char **mysql_error*(MYSQL *mysql)'
     The error message from last *MySQL* function.

`MYSQL_FIELD **mysql_fetch_field*(MYSQL_RES *handle)'
     Find out what type a table field is.

     When querying for the length of a `BLOB' without retreving a result
     *MySQL* returns the 'default blob length', which is 8192, when
     doing a select on the table. When one retrevies a result,
     column_object->max_length contains the real max_length for the
     specific query.

     The 8192 is chosen because *MySQL* doesn't know the max length for
     the blob object. This should be made configurable sometime.

`unsigned int **mysql_fetch_lengths*(MYSQL_RES *mysql)'
     Returns the length of all columns in a query result set.

`MYSQL_ROW *mysql_fetch_row*(MYSQL_RES *mysql)'
     Fetch the 'next' row in the query result.

`void *mysql_field_seek*(MYSQL_RES *result, int field)'
     Put the column cursor on column number field.

`void *mysql_free_result*(MYSQL_RES *result)'
     Free memory used to store a query result.

`char **mysql_get_client_info*(void)'
     Return version information for the current client library.

`char **mysql_get_host_info*(MYSQL *mysql)'
     Returns name of server host.

`int *mysql_get_proto_info*(MYSQL *mysql)'
     Get protocol version used by connection.

`char **mysql_get_server_info*(MYSQL *mysql)'
     Returns the version number of the server.

`int *mysql_insert_id*(MYSQL *mysql)'
     Returns ID generated for AUTO_INCREMENT field.

`MYSQL_RES **mysql_list_dbs*(MYSQL *mysql, const char *wild)'
     Return maching database names.

`MYSQL_RES **mysql_list_fields*(MYSQL *mysql, const char *table, const char *wild)'
     Return maching field names.

`MYSQL_RES **mysql_list_processes*(MYSQL *mysql)'
     Get a list of the current server threads.

`MYSQL_RES **mysql_list_tables*(MYSQL *mysql, const char *wild)'
     Return maching table names.

`int *mysql_num_fields*(MYSQL_RES *result)'
     Return the number of columns in a result set.

`int *mysql_num_rows*(MYSQL_RES *result)'
     Returns the number of rows in result set.

`int *mysql_query*(MYSQL *mysql, const char *query)'
     Executes a SQL query.

`int *mysql_real_query*(MYSQL *mysql, const char *query, uint length)'
     Executes a SQL query with length information.

`int *mysql_reload*(MYSQL *mysql)'
     Reload the user permissions table in the server.

`int *mysql_select_db*(MYSQL *mysql, const char *db)'
     Connect to a database.

`int *mysql_shutdown*(MYSQL *mysql)'
     Shut down the database server.

`char **mysql_stat*(MYSQL *mysql)'
     Return server status in a string.

`MYSQL_RES **mysql_store_result*(MYSQL *mysql)'
     Reads a result set to the client.

`MYSQL_RES **mysql_use_result*(MYSQL *mysql)'
     Initiate a dynamic result set for each row.

Why is it that after `mysql_query()' returns success, `mysql_store_result()' sometimes returns NULL?
----------------------------------------------------------------------------------------------------

   It means one of the following:

  1. Malloc failure.

  2. The data couldn't be read (Error on connection).

  3. The statement was a statement which never returns data (`INSERT'
     or `UPDATE' or `DELETE').

   You can always check if the statement should have given a result by
checking that `mysql_num_columns(MYSQL *)' isn't 0. If this is 0 the
last query was a statement that does not return values. For example a
`INSERT' or a `DELETE'.

   You have got an error if `mysql_error(MYSQL *)' isn't empty!

What results can I get from a query?
------------------------------------

   `mysql_affected_rows(MYSQL *)' returns the number of affected rows
in the last query when doing an INSERT, UPDATE or DELETE. Except, if
DELETE is used without a where clause then the table is truncated which
is much faster!. In this case it returns records affected as zero.

   `mysql_insert_id(MYSQL *)' returns the given ID of the last query
when inserting a row into a table with a `AUTO_INCREMENT' index.  *Note
mysql_insert_id::

   Some queries, `LOAD DATA INFILE...' and `INSERT INTO ... SELECT
...', return additional info.  The result is returned in
`mysql_info(MYSQL *)'. `mysql_info()' returns a null pointer if there
is no additional information.

How can I get the unique ID for the last inserted row?
------------------------------------------------------

   If you insert a record that has a `AUTO_INCREMENT' index then you
can get the given id with `mysql_insert_id(MYSQL *)'.

   The last value is also stored in the server and can be retrieved with
the `LAST_INSERT_ID()' function.

   You can check if an auto_increment index is used by the following
code. This also checks if the query was a insert with a
`auto_increment' index.

     if (mysql_error(MYSQL)[0] == 0 &&
         mysql_num_fields(MYSQL_RESULT) == 0 &&
         mysql_insert_id(MYSQL) != 0)
       used_id = mysql_insert_id(MYSQL);

   The id that `LAST_INSERT_ID()' returns is maintained in the server
per connection. It will not be botched by another client. It will not
even be changed if you update another auto_increment column with a non
magic value (that is a not null or 0).

What is the difference between `mysql_use_result()' and `mysql_store_result()' modes?
-------------------------------------------------------------------------------------

   `mysql_use_results' reads the result directly from the server without
storing it in a local buffer. This is somewhat faster and uses much less
memory thatn `mysql_store_result'. One shouldn't use
`mysql_use_results' if there is a lot of processing being done for each
row at the client side, or if the output is sent to a screen on which
the user may do a ^S (stop scroll). Doing this would tie up the server
and then other threads can't update the used tables. One can't use
`mysql_data_seek' or issue other queries while using `mysql_use_result'.

Problems linking with C API.
----------------------------

   When linking with the C API you can get the following errors on some
systems:

     gcc -g -o client test.o -L/usr/local/lib/mysql -lmysqlclient -lsocket -lnsl
     
     Undefined        first referenced
      symbol          in file
     floor            /usr/local/lib/mysql/libmysqlclient.a(password.o)
     ld: fatal: Symbol referencing errors. No output written to client

   This means that on your system you have to include the math library
(-lm) last in the compile/link line.

How to make a threadsafe client
-------------------------------

   The client is 'almost' thread-safe. The biggest problem is that
net.c (the subroutines that read from sockets) are not interrupt safe.
This was done with the thought that one may want to have one's own alarm
that can break a long read to a server.

   The standard client libraries are not compiled with the thread
options.

   To get a thread safe client use the `-lmysys', `-lstring' and
`-ldbug' libraries and `net_serv.o' that the server uses.

   When using a threaded client I think one can have great use of the
thr_alarm.c routine. If you are using the mysys routines, the only
thing one has to remember is to call my_init() first!

Making a threadsafe client
--------------------------

   All functions except mysql_connect() are currently thread safe.

   To get connect thread_safe you have to do the following:

   Recompile the client with:

     CPPFLAGS=-DTHREAD_SAFE_CLIENT ./configure ...

   You may get some errors because of undefined symbols when linking the
standard client as the pthread libraries are not included by default.

   The resulting libmysqld.a library is now thread safe.

   Two treads can't use the same handle (returned by `mysql_connect()')
at the same time, even if two threads can use different `MYSQL_RES'
handles that was created with `mysql_store_result()'.

   When using a threaded client one can have great use of the
thr_alarm.c routine. If you are using the mysys routines, the only
thing one has to remember is to call my_init() first!

*MySQL* Perl API's
==================

   Since `DBI/DBD' now is the recommended perl interface mysqlperl is
not documented here.

`DBI' with `DBD::mysql'
-----------------------

   `DBI' is a generic interface for many databases. That means that you
can write a script what works with many different database engines
without change. You need a DataBase Driver (DBD) defined for each
database type. For *MySQL*, this driver is called `DBD::mysql'.

   For more information on the Perl5 DBI, please visit
DBIs web page (http://www.hermetica.com/technologia/DBI) and read the
documentation. For more information on Object Oriented Programming
(OOP) as defined in Perl5, see
The perl OOP page (http://language.perl.com/info/documentation.html).

The DBI interface
.................

   *Portable DBI methods.*

connect                Establish a connection to a database server        
prepare                Get a SQL statement ready for execution            
do                     Prepares and executes a SQL statement              
disconnect             Disconnect from the database server                
quote                  Quote strings/blobs to be inserted                 
execute                Executes prepared statements                       
fetchrow_array         fetch the next row as an array of fields.          
fetchrow_arrayref      fetch next row as a reference array of fields      
fetchrow_hashref       fetch next row as a reference to a hashtable       
fetchall_arrayref      Get all data as a array of arrays                  
finish                 finish a statment and let the system free          
                       resources                                          
rows                   Returns the number of rows affected                
data_sources           Return an array of databases available on          
                       localhost                                          
ChopBlanks             Shall fetchrow trim spaces                         
NUM_OF_PARAMS          Number of placeholders in the prepared statement   
NULLABLE               Which columns can be NULL                          

   *MySQL specific methods.*

insertid               The latest auto_increment value                    
is_blob                Which column ar BLOBs                              
is_key                 Which columns are keys                             
is_num                 Which columns are numeric                          
is_pri_key             Which columns are primary keys                     
is_not_null            Which columns can NOT be NULL. See NULLABLE        
length                 Maximum theoretically possible column sizes        
max_length             Maximum physical present column sizes              
NAME                   Column names                                       
NUM_OF_FIELDS          Number of fields returned.                         
table                  Table names in returned set                        
type                   All coulumn types                                  
_CreateDB              Create a database                                  
_DropDB                Drop a database. *THIS IS DANGEROUS*               

`connect'
     You use the connect method to make a database connection to the
     data source. The `$data_source' value should begin with
     `DBI:driver_name:'.  Example connect methods with the `DBD::mysql'
     driver:
          $dbh = DBI->connect("DBI:mysql:$database", $user, $password);
          $dbh = DBI->connect("DBI:mysql:$database:$hostname",
                              $user, $password);
          $dbh = DBI->connect("DBI:mysql:$database:$hostname:$port",
                              $user, $password);
     If the username and/or password are undefined, then the DBI will
     use the values of the `DBI_USER', `DBI_PASS' environment variables
     respectively. If you don't specify a hostname, then it will
     default to `"localhost"'. If you don't specify a port, then it
     defaults to the default mysql port (3333).

`prepare'
     Prepare gets a SQL statement ready for execution by the database
     engine and returns a statement handle `($sth)' which invokes the
     execute method. Example:
          $sth = $dbh->prepare($statement) or die "Can't prepare $statement:
          $dbh->errstr\n";

`do'
     The "do" method prepares and executes a SQL statement and returns
     the number of rows effected. This method is generally used for
     "non-select" statements which can not be prepared in advance
     (driver limitation) or which do not need to executed more than
     once (inserts, deletes, etc.). Examples:
          $rc = $dbh->do($statement) or
                  die "Can't execute $statement: $dbh- >errstr\n";

`disconnect'
     Disconnect will disconnect the database handle from the database.
     This is typically called right before you exit from the program.
     Example:
          $rc = $dbh->disconnect;

`quote'
     The quote method is used to "escape" any special characters
     contained in the string and to add the required outer quotation
     marks.
          $sql = $dbh->quote($string)

`execute'
     This method executes the prepared statement. For non-select
     satements, it returns the number of rows affected. For select
     statements, execute only starts the SQL query in the database. You
     need to use one of the `fetch_*' methods below to retrieve the
     data.  Example:
          $rv = $sth->execute or die "can't execute the query: $sth->errstr;

`fetchrow_array'
     This method "fetches" the next row of data and returns it as an
     array of field values.  Example:
          while(@row = $sth->fetchrow_array) {
                  print qw($row[0]\t$row[1]\t$row[2]\n);
          }

`fetchrow_arrayref'
     This method "fetches" the next row of data and returns it as a
     reference to an array of field values. Example:
          while($row_ref = $sth->fetchrow_arrayref) {
                  print qw($row_ref->[0]\t$row_ref->[1]\t$row_ref->[2]\n);
          }

`fetchrow_hashref'
     This method fetches a row of data and returns a reference to a hash
     table containing field name/value pairs. This method is not nearly
     as efficient as using array references as demonstrated above.
     Example:
          while($hash_ref = $sth->fetchrow_hashref) {
                  print qw($hash_ref->{firstname}\t$hash_ref->{lastname}\t\
                          $hash_ref- > title}\n);
          }

`fetchall_arrayref'
     This method is used to get all the data (rows) to be returned from
     the SQL statement. It returns a reference to an array of arrays of
     references to each row. You access/print the data by using a nested
     loop. Example:
          my $table = $sth->fetchall_arrayref or die "$sth->errstr\n";
          my($i, $j);
          for $i ( 0 .. $#{$table} ) {
                  for $j ( 0 .. $#{$table->[$i]} ) {
                          print "$table->[$i][$j]\t";
                  }
                  print "\n";
          }

`finish'
     Indicates that no more date will be fetched from this statement
     handle. You call this method to free up the statement handle and
     any system resources it may be holding.  Example:
          $rc = $sth->finish;

`rows'
     Returns the number of rows affected (updated, deleted, etc.) from
     the last command.  This is usually used after a do() or non-select
     execute() statement.
          $rv = $sth->rows;

`NULLABLE'
     A reference to an array of boolean values; TRUE indicates that this
     column may contain NULL's.
          $null_possible = $sth->{NULLABLE};

`NUM_OF_FIELDS'
     Number of fields returned by a SELECT or LISTFIELDS statement.
     You may use this for checking whether a statement returned a
     result: A zero value indicates a non-SELECT statement like INSERT,
     DELETE or UPDATE.
          $nr_of_fields = $sth->{NUM_OF_FIELDS};

`data_sources'
     This method returns an array of databases available to the mysql
     daemon on localhost.
          @dbs = DBI->data_sources("mysql");

`ChopBlanks'
     This determines whether a fetchrow will chop preceding and trailing
     blanks off the returned values.
          $sth->{'ChopBlanks') =1;

   *MySQL specific methods.*

`insertid'
     If you use the auto-increment feature of mysql, the new
     auto-incremented values will be stored here.
          $new_id = $sth->{insertid};

`is_blob'
     Reference to an array of boolean values; TRUE indicates, that the
     respective column is a blob.
          $keys = $sth->{is_blob};

`is_key'
     Reference to an array of boolean values; TRUE indicates, that the
     respective column is a key.
          $keys = $sth->{is_key};

`is_num'
     Reference to an array of boolean values; TRUE indicates, that the
     respective column contains numeric values.
          $nums = $sth->{is_num};

`is_pri_key'
     Reference to an array of boolean values; TRUE indicates, that the
     respective column is a primary key.
          $pri_keys = $sth->{is_pri_key};

`is_not_null'
     A reference to an array of boolean values; FALSE indicates that
     this column may contain NULL's. You should better use the NULLABLE
     attribute above which is a DBI standard.
          $not_nulls = $sth->{is_not_null};

`max_length'
`length'
     A reference to an array of maximum column sizes. The max_length is
     the maximum physically present in the result table, length gives
     the theoretically possible maximum.
          $max_lengts = $sth->{max_length};
          $lengts = $sth->{length};

`NAME'
     A reference to an array of column names.
          $names = $sth->{NAME};

`table'
     Returns a reference to an array of table names.
          $tables = $sth->{table};

More DBI/DBD information
........................

   You can use the perldoc command to get more information about DBI.

     perldoc DBI
     perldoc DBI::FAQ
     perldoc mysql

   You can also use the `pod2man', `pod2html', etc.. tools to translate
to other formats.

   And of course you can find the latest DBI information at
http://www.hermetica.com/technologia/DBI, the DBI web page
  And of course you can find the latest DBI information at
the DBI web
page lt table, length gives      the theoretically possible maximum.

   d.

   ment like INSERT,      DELETE or UPDATE.

   [$j]\t";                   }                   print "\n";
}

   amples: 3).

   screen on which the user may do a ^S (stop scroll). Doing this would
tie up the server and then other threads can't update the used tables.
One can't use `mysql_data_seek' or issue other queries while using
`mysql_use_result'.

   ANYTHING to do with *MySQL* running as root, as a user or as anyone
else. The access permissions and userbase of *MySQL* are completely
separate from the UNIX users. The only connection to the UNIX users is
if you don't use the -u option to clients. In this case the client will
try to login into *MySQL* with your UNIX login name. If your UNIX box
itself isn't secured, you should probably at least put a password on
the root users in the *MySQL* access tables, since any johndoe user can
run 'mysql -u root dbname' and do whatever he likes.

   1     1      2     2     4      3     6     4      4     10    1
5     11    20      6     31    1      7     32    30      8     62
35      9     97    35      10    132   35      11    167   4      12
171   16      13    187   35      14    222   4      15    226   16
 16    242   20      17    262   20      18    282   20      19    302
 30      20    332   4      21    336   4      22    340   1      23
341   8      24    349   8      25    357   8      26    365   2
27    367   2      28    369   4      29    373   4      30    377   1
   31    378   2      32    380   8      33    388   4      34    392
4      35    396   4      36    400   4      37    404   1      38
405   4      39    409   4      40    413   4      41    417   4
42    421   4      43    425   4      44    429   20      45    449   30
    46    479   1      47    480   1      48    481   79      49
560   79      50    639   79      51    718   79      52    797   8
53    805   1      54    806   1      55    807   20      56    827   4
    57    831   4            Compressing station.ISD: (1192 records)
  - Calculating statistics            normal:     20  empty-space:
16  empty-zero:        12  empty-fill:  11      pre-space:   0
end-space:        12  intervall-fields:   5  zero:         7
Original trees:  57  After join: 17      - Compressing file      87.14%
          (/my/monty/tmp) ls -l station.*      -rw-rw-r--   1 monty
my         127874 Apr 17 19:00 station.ISD      -rw-rw-r--   1 monty
my          55296 Apr 17 19:04 station.ISM      -rw-rw-r--   1 monty
my           5767 Apr 17 19:00 station.frm            (my/monty/tmp)
isamchk -dvv station            ISAM file:     station
Isam-version:  2      Creation time: 1996-03-13 10:08:58      Recover
time:  1997-04-17 19:04:26      Data records:              1192
Deleted blocks:              0      Datafile: Parts:           1192
Deleted data:                0      Datafilepointer (bytes):      3
Keyfile pointer (bytes):     1      Max datafile length:   16777215
Max keyfile length:     131071      Recordlength:               834
Record format: Compressed            table description:      Key Start
Len Index   Type                       Root  Blocksize    Rec/key
1   2     4   unique  unsigned long             10240       1024
 1      2   32    30  multip. text                      54272
1024          1            Field Start Length Type
  Huff tree  Bits      1     1     1      constant
       1     0      2     2     4      zerofill(1)
    2     9      3     6     4      no zeros, zerofill(1)
 2     9      4     10    1
3     9      5     11    20     table-lockup                         4
  0      6     31    1                                           3
9      7     32    30     no endspace, not_always              5     9
   8     62    35     no endspace, not_always, no empty    6     9
9     97    35     no empty                             7     9
10    132   35     no endspace, not_always, no empty    6     9      11
  167   4      zerofill(1)                          2     9      12
171   16     no endspace, not_always, no empty    5     9      13
187   35     no endspace, not_always, no empty    6     9      14
222   4      zerofill(1)                          2     9      15
226   16     no endspace, not_always, no empty    5     9      16
242   20     no endspace, not_always              8     9      17
262   20     no endspace, no empty                8     9      18
282   20     no endspace, no empty                5     9      19
302   30     no endspace, no empty                6     9      20
332   4      allways zero                         2     9      21
336   4      allways zero                         2     9      22
340   1                                           3     9      23
341   8      table-lockup                         9     0      24
349   8      table-lockup                        10     0      25
357   8      allways zero                         2     9      26
365   2                                           2     9      27
367   2      no zeros, zerofill(1)                2     9      28
369   4      no zeros, zerofill(1)                2     9      29
373   4      table-lockup                        11     0      30
377   1                                           3     9      31
378   2      no zeros, zerofill(1)                2     9      32
380   8      no zeros                             2     9      33
388   4      allways zero                         2     9      34
392   4      table-lockup                        12     0      35
396   4      no zeros, zerofill(1)               13     9      36
400   4      no zeros, zerofill(1)                2     9      37
404   1                                           2     9      38
405   4      no zeros                             2     9      39
409   4      allways zero                         2     9      40
413   4      no zeros                             2     9      41
417   4      allways zero                         2     9      42
421   4      no zeros                             2     9      43
425   4      allways zero                         2     9      44
429   20     no empty                             3     9      45
449   30     no empty                             3     9      46
479   1                                          14     4      47
480   1                                          14     4      48
481   79     no endspace, no empty               15     9      49
560   79     no empty                             2     9      50
639   79     no empty                             2     9      51
718   79     no endspace                         16     9      52
797   8      no empty                             2     9      53
805   1                                          17     1      54
806   1                                           3     9      55
807   20     no empty                             3     9      56
827   4      no zeros, zerofill(2)                2     9      57
831   4      no zeros, zerofill(1)                2     9

   nique  (http://www.hermetica.com/technologia/DBI).

*MySQL* JAVA connectivity (JDBC)
================================

   Insert pointers/descriptions of JDBC.

*MySQL* PHP API's
=================

   Insert pointers/descriptions of PHP.

*MySQL* C++ API's
=================

   Insert pointers/descriptions for C++.

*MySQL* Python API's
====================

   Insert pointers/descriptions for Python.

*MySQL* TCL API's
=================

   Insert pointers/descriptions for TCL.

How does *MySQL* compare with other databases
*********************************************

How does *MySQL* compare with `mSQL'
====================================

   This section has been written by the *MySQL* developers so it should
be read with that in mind. But there are NO factual errors that we know
of.

   For a list of all supported limits, functions and types see the
crash-me web page (http:www.tcx.se/crash-me.html).

*Performance.*
     For a true comparison of speed use the growing *MySQL* benchmarka
     suite. *Note Benchmarks::

     *MySQL* is significantly quicker on complex selects.

     `mSQL' can get patalogically slow if you chage the order of tables
     in a select. In the benchmark suite a time more that 15000 times
     slower than *MySQL* was seen.

     Because of no thread creation overhead, small parser, few features
     and simple security `mSQL' should be quicker at:

          Test that do a lot of connect/disconnect with a very simple
          query.  Inserts into very simple tables with few columns and
          keys.

        * `CREATE TABLE' and `DROP TABLE'.

        * `SELECT' one something that isn't a index. (A table scan is
          very easy)

     As these operations are so simple, it is hard to be better at them
     when you have a higher start overhead. After the connection is
     established *MySQL* should perform much better.

     *MySQL* on the other hand is much faster than `mSQL' and most
     other SQL implementions on the following:

          Retrieving large results (*MySQL* has a better, faster and
          safer protocol)

        * Tables with variable length strings since *MySQL* has more
          efficent handling and can have indexs on varchars.

        * Handling tables with many columns.

        * Handling tables with large record lengths.

        * SELECT with many expressions.

        * SELECT on large tables.

        * Handle many connections at the same time. *MySQL* is fully
          multi-threaded. Each connection has it is own thread, which
          means that none of them has to wait for the other (unless a
          query modifying the same table you need to use is executed).
          In `mSQL' all other connections have to wait until the first,
          doesn't matter whether the query is long or short, is
          executed and finished. After that the next connection can be
          served, while all the others wait again, etc.

        * Joins (We have seen (*Note Benchmarks::) speed differences of
          17000 times on this one).

        * `ORDER BY' and `GROUP BY'.

        * `DISTINCT'.

        * Using `TEXT' or `BLOB' columns.

*SQL Features*
       1. `GROUP BY' & `HAVING' *MySQL* supports a full `GROUP BY' with
          both `HAVING' and the following functions `count()', `avg()',
          `min()', `max()', `sum()' and `std()'. `min()' and `max()'
          may take string arguments. `count(*)' is optimised to return
          very quickly if this is the only thing in the query. `mSQL'
          does not support `GROUP BY' at all.

       2. `INSERT' & `UPDATE' with calculations.  *MySQL* can do
          calculations in a `INSERT' or `UPDATE'.
               UPDATE SET x=x*10+y WHERE x<20;

       3. Aliasing *MySQL* has column aliasing.

       4. Qualifying column names.  If a column name is unique you do
          not have to use the full qualifier.

       5. `SELECT' with functions *MySQL* has too many functions to
          list here. *Note Functions::.


*Disk space efficiency*
     That is, how small can you make your tables.

     MySQL has very precise types so that use can create tables that
     take very little space. An example of a useful *MySQL* datatype is
     the mediumint that is 3 bytes long. If you have 10.000.0000
     records even saving one byte per record is very important.

     Since `mSQL2' only has 4 types (char,text,int,real) it is hard to
     get small tables.

*Stability*
     This is harder to judge objectively. For *MySQL* stability see
     *Note Stability::.

     We have no experience with `mSQL' stability so we can not say
     anything about that.

*Price*
     Another important issue is of course the license. *MySQL* has a
     more flexible license than `mSQL' and is also cheaper than `mSQL'.
     Remember to at least consider paying for a license or email
     support for whatever product you choose to use. If you sell a
     product with *MySQL* you are of course required to get a license
     for this.

*Perl interfaces*
     MySQL has basically the same interfaces to perl as `mSQL' with some
     added features.

*JDBC (Java)*
     MySQL has a java interface by GWE technologies that has been
     improved by Xiaokun Kelvin ZHU.

     We know that `mSQL' has one but we have too little experience with
     it to compare.

*Rate of development*
     MySQL has a very small team of developers, but we are quite use to
     coding C and C++ very rapidly. Since threads, functions, group by
     and so on are still not implemented in `mSQL', it has a lot of
     catching up to do. To get some perspective on this you can view
     the `mSQL' HISTORY file for the last year and compare it with the
     News section. *Note News::. It should be pretty obvious which one
     has developed most rapidly.

*Utility programs*
     Both `mSQL' and *MySQL* has a lot of interesting third party
     tools. Since it is very easy to port upwars (`mSQL' -> *MySQL*)
     *MySQL* has almost all interesting `mSQL' applications.

     MySQL comes with a simple msql2mysql program that fixes the
     different spelling of the most used functions. A conversion of a
     client program from `mSQL' to mySQL usually takes a couple of
     minutes.

How about `mSQL' tools like msql-tcl, msqljava?
-----------------------------------------------

   According to our experience it would just take a few hours to
convert a tool using the `mSQL' C API to the *MySQL* C API.

   The procedure:

  1. Run the shell script msql2mysql on the source. This needs the
     binary program replace, which is distributed with *MySQL*.

  2. Compile

  3. Fix all compiler errors:

   Differences between the *MySQL* and `mSQL' C API's.
   * MySQL uses *MySQL* as a connection type (`mSQL' uses an `int').

   * MySQL connect takes a pointer to a MYSQL structure as a parameter.
     It is easy to define one globally or use malloc to get one.

   * mysql_connect takes 2 extra parameters. You may set these to
     NULL,NULL for default use (user and password).

   * mysql_error takes the MYSQL structure as a parameter. Just add the
     parameter to your old msql_error code if you are porting old code.

   * Some incompatibilities exist as a result of *MySQL* supporting
     multiple connections to the server from the same process.

   * *MySQL* returns a error number and a text for all errors. `mSQL'
     only returns a text error

How different from `mSQL' are the *MySQL* client/server communications protocols?
---------------------------------------------------------------------------------

   There are enough differences that it is impossible (at least not
easy) to support both.

   The greatest differences between *MySQL* and `mSQL' are:

   * A message buffer may contain many result rows.

   * The message buffers are dynamically enlarged if the question or the
     result is bigger than the current buffer up to a configurable
     server and client limit.

   * All packages are numbered to catch out dupplicated or missing
     packets.

   * All columns are sent in ASCII, the length of columns and rows are
     sent in packed binary coding (1,2 or 3 bytes).

   * MySQL can read in the result unbuffered (without having to store
     the full set in the client).

   * If a single write/read takes more than 30 seconds then the server
     closes the connection.

   * If nothing has happened on a connection for 8 hours the server
     closes the connection.

What are the differences in the SQL syntax between *MySQL* & `mSQL' 2.0?
------------------------------------------------------------------------

   * `CREATE TABLE'

    `*MySQL*'
          Has (among others) the following extra types: *Note Create
          table::
             - `UNSIGNED' option for all integer columns.

             - `ZEROFILL' option for all integer columns.

             - `AUTO_INCREMENT' option for all integer columns that
               also is a `PRIMARY KEY'. *Note mysql_insert_id::.

             - `DEFAULT' value for all columns.

             - `ENUM' type for one of a set of strings.

             - `SET' type for many of a set of string.

             - `BIGINT' type for 64 bit integers.

    `mSQL2'
          `mSQL' type         Corresponding *MySQL* type.                 
          char(len)           char(len)                                   
          text(len)           text(len). len is the maximal length. And   
                              `LIKE' works.                               
          int                 int. With many more options!                
          real                real. Or float. Both 4 and 8 bytes          
                              versions are available.                     
          uint                Unsigned integer.                           
          date                date. Takes ANSI SQL format instead of      
                              `mSQL's own.                                
          time                time                                        
          money               decimal(12,2). A fixed point value with     
                              two decimals.                               

   * To create indexes.
    `*MySQL*'
          All indexes have to be given to `CREATE TABLE'. Indexes can
          not be removed without recreating the table. *Note Alter
          table::.

    `mSQL'
          Indexes must be created by a separate `CREATE INDEX' clause.
          Indexes may be removed with `DROP INDEX'.

   * To get a unique identifier in a table at insert.
    `*MySQL*'
          Use `AUTO_INCREMENT' as a column type specifier. *Note
          mysql_insert_id::.

    `mSQL'
          Create a `SEQUENCE' on a table and select the `_seq' column.

   * To get a unique identifier for a row.
    `*MySQL*'
          Add a `PRIMARY KEY' to the table.

    `mSQL'
          Use the `_rowid' column. Observe that `_rowid' may change
          depending on many factors.

   * Get the time a column was last modified.
    `*MySQL*'
          Add a `TIMESTAMP' column to the table. And insert update it
          with a `NULL' value. It when sutomaticaly gets the current
          time.

    `mSQL'
          Use the `_timestamp' column.

   * Case insensitive searching.
    `*MySQL*'
          `LIKE' is always case insensitive. Also if possible *MySQL*
          uses indexes if the like argument doesn't start with a
          wild-card.

    `mSQL'
          Use `CLIKE'.

   * End space handling.
    `*MySQL*'
          Stripps all spaces att the end of `CHAR' and `VARCHAR'
          columns. Currently use a `TEXT' column if this behavior is
          undesired.

    `mSQL'
          Keeps end space.

   * What are the differences in the `WHERE' statement?
    `*MySQL*'
          *MySQL* does everything correctly prioritized (AND is
          evaluated before OR). To get `mSQL' behaviour in *MySQL*, use
          parenthesis: `select * from table where a=1 and b=2 or a=3
          and b=4' -> `select * from table where (a=1 and (b=2 or (a=3
          and (b=4))))'.

    `mSQL'
          Evaluates everything from left to right. That means that some
          logical calculation with more that 3 arguments can not be
          expressed in any way. This also mean that you have to change
          some queries when you upgrade to *MySQL*. You do this easy by
          adding parenthesis.

          Always when you are in doubt about what a query does:

            1. Remove all distinct keywords to make the query easier to
               debug.

            2. Write all columns from all tables to really see what you
               are doing.

          This will make it easier to see what goes wrong.

   * Access Control
    `*MySQL*'
          Has tables to store grant options per user, host and db.
          *Note Privileges::

    `mSQL'
          Has a file `mSQL.acl' where you can grant read/write
          privileges for users.

    `'
How does *MySQL* compare with PostgreSQL
========================================

   For a list of all supported limits, functions and types see the
crash-me web page (http:www.tcx.se/crash-me.html).

   PostgreSQL has some more advanced features like user defined types,
triggers, rules and transactions. But it lacks a lot of the standard
types and functions from ANSI SQL and ODBC. See the
crash-me web page (http:www.tcx.se/crash-me.html) for a complete list
of supported/unsupported types/function.

   Normally PostgreSQL is much slower than *MySQL*. *Note Benchmarks::.

Some users of *MySQL*.
**********************

   * Some Web search engines:
        - AAA Matilda Web Search (http://www.aaa.com.au)

        - What's New (http://www.whatsnu.com/)

        - Aladin (http://www.aladin.de/)

        - Columbus Finder (http://www.columbus-finder.de/)

        - Spider (http://www.spider.de/)

        - Blitzsuche (http://www.blitzsuche.de/)

   * Some Domain/Internet and Web service providers:
        - Monolith Internet Services (http://www.ml.org) runs *MySQL*
          supporting nearly a million rows and over 100,000 users.

        - Registry over Web providers           who supports *MySQL* (http://www.wix.com/mysql-hosting)

   * Internet information server (http://online.garant.ru)

   * AZC.COM's      Feature Showcase (http://www.feature-showcase.com/htmls/demo_mysql.sql)

   * The Music Database (http://www.musicdatabase.com/)

   * Musical note-sheets (http://www.kiss.de/musik-mueller/)

   * Musician's looking      for other musicians (Free Service) (http://TheMatrix.com/~matrix/band_search.phtml)

   * Course      Search (http://www.teach.org.uk/subjects/trainingcourse/g.html)

   * Northerbys Online Auctions (http://www.northerbys.com)

   * Hawkeye (http://www.hawkeye.net)

   * Amsterdam Airport Schiphol
     (http://www.schiphol.nl/flights/home.htm)

   * CD database (http://TheMatrix.com/seventhsin/query.phtml)

   * Used Audio Gear Database (http://TheMatrix.com/~flmm/GEAR.html)

   * US Folk art broker (http://www.selftaught.com/)

   * Mail reading on the web (http://organizer.net/)

   * Free home pages on      www.somecoolname.mypage.org (http://www.mypage.org/)

   * Der Server fьr Schulen im Web (In German) (http://www.schulweb.de/)

   * Auldhaefen Online Services (http://www.ald.net/)

   * CaryNET Information Center (http://www.cary.net/)

   * Dataden Computer Systems (http://www.dataden.com/)

   * Andrйemuseet (In Swedish) (http://andree.grm.se/)

   * HOMESITE Internet Marketing (http://www.him.net/)

   * Jade-V Network Services  (http://www.jade-v.com/techinfo.html)

   * Weather      World 2010 Technical Credits (http://ww2010.atmos.uiuc.edu/(Gl)/abt/aknw/tech.rxml)

   * About The Gimp plugin      registry (http://gimp.foebud.org/registry/doc/)

   * JAVA tool      Archiver technical detail (Slightly optimistic about ANSI-92      complicate) (http://www.fast-inc.com/Products/Archiver/database.html)

   * Games Domain      Cheats Database (http://www.gamesdomain.com/cheats/usrcheat.phtml)

   * The "Powered By" Page (Kcilink) (http://www.kcilink.com/poweredby/)

   * Netcasting (http://www.netcasting.net/index.whtml)

   * CGI shop (http://www.cgishop.com/)

Who has helped to make *MySQL*.
*******************************

   Contributors to the *MySQL* distribution in somewhat random order:

Michael (Monty) Widenius
     Has written the following parts of *MySQL*:
        * All the main code in `mysqld'.

        * New functions for the string library.

        * Most of the mysys library.

        * The `MISAM' library (A B-tree index file handler with index
          compression and different record formats).

        * The heap library. A memory table system with our superior
          full dynamic hashing. In use since 1981 and published around
          1984.

        * replace (Look into it, it's COOL!).

        * myodbc, the ODBC driver for Windows95.

        * Fixing bugs in MIT threads to get it to work for *MySQL*. And
          also UNIREG A curses based application tool with lot of
          utilities.

        * Porting of `mSQL' tools like msqlperl, DBD/DBI and DB2mysql.

David Axmark
        * Coordinator and main writer for the *Reference Manual*
          including enhancements to `texi2html'. Also automatic website
          updating from this manual.

        * autoconf & automake support.

        * The licensing stuff.

        * Parts of all the text files. Now days only the `README' is
          left. The rest ended up in the manual.

        * Our Mail master.

        * Lots of testing of new features.

        * Our in house 'free' software lawyer.

        * Mailing list maintainer (who never has the time to do it
          right...)

        * Our original portability code (more than 10 years old now).
          Now days only some parts of mysys are left.

        * Someone for Monty to call in the middle of the night when he
          just got that new feature to work :-)

Kim Aldale
     Rewriting Monty's and David's attempts at English into English.

Allan Larsson (The BOSS at TcX)
     For all the time he has allowed Monty to spend on this 'maybe
     useful' tool (*MySQL*). Dedicated user (and bug finder) of UNIREG
     & *MySQL*.

Per Eric Olsson
     For more or less constructive criticism and real testing of the
     dynamic record format.

David J. Hughes
     For the effort to make a shareware SQL database. We at TcX started
     with mSQL but found that it couldn't satisfy our purposes so
     instead we wrote a SQL interface to our application builder
     UNIREG.  mysqladmin & mysql are programs that were largely
     influenced by their mSQL counterparts. We have put a lot of effort
     into making the *MySQL* syntax a superset of mSQL. Much of the
     API:s ideas are borrowed from mSQL to make it easy to port free
     mSQL programs to *MySQL*. *MySQL* doesn't contain any code from
     mSQL. Two files (`client/insert_test.c' and
     `client/select_test.c') in the distribution are non copyrighted
     files from the mSQL distribution (Copyrighted David J. Hughes).
     These are included as a example of the changes that must be done
     to change from mSQL to *MySQL*.

Fred Fish
     For his excellent C debugging and trace library. Monty has made a
     number of smaller improvements to the library (speed and
     additional options).

Richard A. O'Keefe
     For his public domain string library.

Henry Spencer
     For his regex library, used in 'WHERE column REGEXP regexp'.

Free Software Foundation
     From whom we got an excellent compiler (gcc) and for their libc
     from which I have borrowed strto.c to get some code working in
     Linux. Also readline for the client.

Free Software Foundation & The XEmacs development team
     For a really great editor/environment used by almost everybody at
     tcx/detron.

Igor Romanenko (igor@frog.kiev.ua)
     mysqldump  (Previously msqldump but ported and enhanced by Monty)

Tim Bunce, Alligator Descartes
     For the DBD (perl) interface.

Andreas Koenig <a.koenig@mind.de>
     For the perl interface to *MySQL*

Eugene Chan <eugene@acenet.com.sg>
     For porting PHP to *MySQL*.

Michael J. Miller Jr. <mke@terrapin.turbolift.com>
     For the growing *MySQL* user manual. And a lot of
     spelling/language fixes for the FAQ.

Giovanni Maruzzelli <maruzz@matrice.it>
     For porting iODBC (unix ODBC).

Chris Provenzano
     Portable user level pthreads. From the copyright: This product
     includes software developed by Chris Provenzano, the University of
     California, Berkeley, and contributors.  We are currently using
     version 1_60_beta6 patched by Monty (se
     mit-pthreads/Changes-mysql).

Xavier Leroy <Xavier.Leroy@inria.fr>
     The author of LinuxThreads (used by *MySQL* on Linux).

Zarko Mocnik <zarko.mocnik@dem.si>
     Sorting for Slovenian language and the cset.tgz module for easier
     adding of other character sets.

Yves Carlier Yves.Carlier@rug.ac.be
     mysqlaccess ; A program to show how the access right for a user.

Rhys Jones <rhys@wales.com> (And GWE Technologies Limited)
     For the JODBC; A module to extract data from *MySQL* with a Java
     client.

Dr Xiaokun Kelvin ZHU <X.Zhu@brad.ac.uk>
     Futher development of the JDBC driver and other *MySQL* related
     JAVA tools.

James Cooper <pixel@organic.com>
     For setting up a searchable mailing list archive at his site.

Rick_Mehalick <Rick_Mehalick@i-o.com>
     For xmysql a graphical X client for *MySQL*.

Doug Sisk <sisk@wix.com>
     For providing RPM packages of *MySQL* for RedHat Linux.

Jochen Wiedmann <wiedmann@neckar-alb.de>
     Maintaining of the perl module DBD::mysql

Therrien Gilbert <gilbert@ican.net>
     French error messages.

Petr snajdr, <snajdr@pvt.net>
     Czech error messages.

Jaroslaw Lewandowski <jotel@itnet.com.pl>
     Polish error messages

Miguel Angel Fernandez Roiz
     Spanish error messages

Roy-Magne Mo <rmo@www.hivolda.no>
     Norwegian error messages and testing of 3.21.#

Timur I. Bakeyev <root@timur.tatarstan.ru
     Russian error messages

David Sacerdote <davids@secnet.com>
     Ideas for secure checking of DNS hostnames

Gianmassimo Vigazzola" <qwerg@mbox.vol.it> or <qwerg@tin.it>
     Port to Win32/NT.

Irena Pancirov <irena@mail.yacc.it>
     Win32 port with Borland compiler.

Wei-Jou Chen <jou@nematic.ieo.nctu.edu.tw>
     Some support for Chinese(BIG5) characters.

Zeev Suraski <bourbon@netvision.net.il>
     from_unixtime time formating, ENCRYPT() functions, and bison
     adviser.  Active mailing list member.

Luuk de Boer <luuk_de_boer@pi.net>
     Ported (and extended) the benchmark suite to DBI/DBD.  Some new
     date functions.

Jay Flaherty <fty@utk.edu>
     Big parts of the perl DBI/DBD section.

   Other contributors, bugfinders and testers: James H. Thompson,
Maurizio Menghini, Wojciech Tryc, Luca Berra, Zarko Mocnik, Wim Bonis,
Elmar Haneke, jehamby@lightside, psmith@BayNetworks.COM,
duane@connect.com.au, root@dondra.ofc.psyber.com

   And lots of bug report/patches from the folks on the mailing list.

   And a big tribute to those that helps us answer question on the
mysql@tcx.se mailing list.

"Daniel Koch" <dkoch@amcity.com>
     IRIX setup.

"Luuk de Boer" <luuk_de_boer@pi.net>
     Benchmark questions.

Tim Sailer <tps@users.buoy.com>
     DBD-mysql questions.

"Boyd Lynn Gerber (801) 250-O795 Work" <gerberb@zenez.com>
     SCO related questions.

"Mehalick RE (Richard)  at MSXSEPC" <RM186061@shellus.com>
     XmySQL releated questions and basic installation questions.

Zeev Suraski <bourbon@netvision.net.il>
     Apache module configuration questions (log & auth), PHP related
     questions, SQL syntax related questions and other general
     questions.

Francesc Guasch <frankie@citel.upc.es>
     General questions

Jonathan J Smith <jsmith@wtp.net>
     Questions pertaining to OS specifics with Linux, SQL syntax, and
     other things that might be needing some work.

David Sklar <sklar@student.net>
     Using *MySQL* from PHP and Perl.

Alistair MacDonald <A.MacDonald@uel.ac.uk>
     Not yet specified, but is flexible and can handle Linux and maybe
     HP/UX.  Will try to get user to use mysqlbug.

John Lyon <jlyon@imag.net>
     Questions about installing *MySQL* on Linux systems, using either
     .rpms, or compiling from source.

"Lorvid Ltd." lorvid@WOLFENET.com
     Simple billing/license/support/copyright issues.

Patrick Sherrill <patrick@coconet.com>
     ODBC and VisualC++ interface questions.

Randy Harmon <rjharmon@uptimecomputers.com>
     DBD, Linux, Some SQL syntax questions.

*MySQL* change history
**********************

Changes in release 3.21.x
=========================

Changes in release 3.21.19
--------------------------

   * Upgraded DBD to 1823. This version implements mysql_use_result in
     DBD-Mysql.

   * Benchmarks updated for empress (by Luuk)

   * Fixed a case of slow range searching.

   * Configure fixes (Docs directory).

   * Added function `REVERSE()' (by Zeev Suraski)

Changes in release 3.21.18
--------------------------

   * Give error message if client C functions are called in wrong order.

   * Added automatic reconnect to the libmysql.c library. If a write
     command fails a automatic reconnect is done.

   * Small sort sets doesn't use temporary files anymore.

   * Upgraded DBI to 0.91

   * Fixed a couple of problems with LEFT OUTER JOIN.

   * Added CROSS JOIN syntax. CROSS is now a reserved word.

   * Recoded yacc/bison stack allocation to be even safer and allow
     *MySQL* to handle even bigger expressions.

   * Fixed a couple of problems with the update log.

   * ORDER BY was slow when used with key ranges.

Changes in release 3.21.17
--------------------------

   * Changed documentation string of -with-unix-socket-path to avoid
     confusion.

   * Added ODBC and ANSI SQL style `LEFT OUTER JOIN'.

   * The following are new reserved words: `LEFT', `NATURAL', `USING'

   * The client library is now using the environment variable
     `MYSQL_HOST' as the default host if it's defined.

   * `SELECT column, SUM(expr)' now returns `NULL' for column when
     there are matching rows.

   * Fixed problem with compare of binary strings and blobs with ASCII
     characters over 127.

   * Fixed lock problem: When freeing a read lock on a table with
     multiple read locks, a thread waiting for write lock would have
     given the lock.  This shouldn't affect data integrity, but could
     possible make mysqld to restart if one thread was reading data
     that another thread modified.

   * LIMIT offset,count didn't work in INSERT ... SELECT.

   * Optimized key block caching. This will be quicker than the old one
     when using bigger key caches.

Changes in release 3.21.16
--------------------------

   * Added ODBC 2.0 & 3.0 functions: `POWER()', `SPACE()', `COT()',
     `DEGREES()', `RADIANS()', `ROUND(2 arg)' and `TRUNCATE()'.

   * *WARNING INCOMPATIBLE CHANGE!!*. `LOCATE()' parameters where
     swapped according to ODBC standard. Fixed.

   * Added function `TIME_TO_SEC()'.

   * In some cases default values was not used for `NOT NULL' fields.

   * Timestamp wasn't updated in `UPDATE SET ...' if the timestamp was
     used as.

   * Allow empty strings as default values for `BLOB' and `TEXT' to be
     compatible with mysqldump.

Changes in release 3.21.15
--------------------------

   * *WARNING INCOMPATIBLE CHANGE!!* mysqlperl is now from
     Msql-Mysql-modules. This means that the connect() now takes
     host,database,user,password ! The old version took
     host,database,password,user.

   * Allow `DATE '1997-01-01'', `TIME '12:10:10'' and `TIMESTAMP
     '1997-01-01 12:10:10'' formats required by ANSI SQL.  *WARNING
     INCOMPATIBLE CHANGE!!* This has the unfortunate side-effect that
     one can't have columns named `DATE', `TIME' or `TIMESTAMP' anymore
     :( Old columns can only be accessed with 'tablename.columnname'!

   * Changed Makefiles to hopefully work better with BSD systems. Also
     manual.dvi is now included in the distribution to avoid having
     stupid makes trying to rebuild it.

   * Readline library upgraded to version 2.1

   * A new sortorder german-1. That is a normal iso-latin1 with a
     german sort order.

   * Perl DBI/DBD is now included in the distribution. DBI is now the
     recommended way to connect to *MySQL* from perl.

   * New portable benchmark suite with DBD, with test results from mSQL
     2.0.3, *MySQL*, PostgreSQL 6.2.1 and Solid server 2.2.

   * crash-me is now included with the benchmarks; This is a perl
     program designed to find as many limits as possible in a SQL
     server. Tested with mSQL, postgreSQL, Solid and *MySQL*.

   * Fixed bug in range-optimizer that crashed mysql on some queries.

   * Table and column name completion for mysql command line tool, by
     Zeev Suraski and Andi Gutmans.

   * Added new command `REPLACE', which works like `INSERT' but
     replaces conflicting records with the new record. `REPLACE INTO
     TABLE ... SELECT ...' works also.

   * Added new commands: `CREATE DATABASE db_name' and `DROP DATABASE
     db_name'.

   * Added `RENAME' option to `ALTER TABLE': `ALTER TABLE name RENAME
     AS new_name'.

   * make_binary_distribution now includes libgcc.a in
     libmysqlclient.a. This should make linking work for people without
     gcc.

   * Changed `net_write()' to `my_net_write()' because of name conflict
     with sybase.

   * New function `DAYOFWEEK()' compatible with ODBC.

   * Stack checking and bison memory overrun checking to get *MySQL*
     safer with weird queries.

Changes in release 3.21.14b
---------------------------

   * Fixed a couple of small configure problems on some platforms.

Changes in release 3.21.14a
---------------------------

   * Ported to SCO Openserver 5.0.4  with FSU-threads.

   * HP-UX 10.20 should work.

   * Added new functions DATE_FORMAT() and DATE_ADD_MM()..

   * Added NOT IN.

   * Added automatic removal of 'ODBC function conversions': {fn now() }

   * Handle ODBC 2.50.3 option flags.

   * Fixed compare of DATE and TIME with NULL.

   * Changed language name from germany to german to be consistent with
     the other language names.

   * Fixed sorting problem on functions returning a float. Before the
     values was converted to a int before sorting.

   * Fixed slow sorting when sorting on key field when using
     KEY_COLUMN=constant.

   * SORTING on calculated DOUBLE values sorted on integer results
     instead.

   * 'mysql' doesn't need a database argument anymore.

   * Changed the place where HAVING should be. According to ANSI it
     should be after GROUP BY but before ORDER BY. *MySQL* 3.20 had it
     wrongly last.

   * Added Sybase command: USE DATABASE to start using another database.

   * Added automatic adjusting of number of connections and table cache
     size if the maximum number of files that can be opened are less
     than needed.  This should fix that mysqld doesn't crash even if
     one hasn't done a ulimit -n 256 before starting mysqld.

   * Added lots of limit checks to make it safer when running with too
     little memory or when doing weird queries.

Changes in release 3.21.13
--------------------------

   * Added retry of interrupted reads and clearing of errno.  This
     makes Linux systems much safer!

   * Fixed locking bug when using many alias on the same table in the
     same select.

   * Fixed bug with LIKE on number key.

   * New error message so one can check if the connection was lost while
     the command was running or if the connection was down from the
     start.

   * Added -table option to mysql to print in table format.  Moved time
     and row information after query result.  Added automatic reconnect
     of lost connections.

   * Added != as an alias for <>.

   * Added function VERSION() to make easier logs.

   * New multi-user test 'tests/fork_test.pl' to put some strain on the
     thread library.

Changes in release 3.21.12
--------------------------

   * Fixed ftruncate() call in MIT-threads. This made isamchk() destroy
     the .ISM files on (Free)BSD systems 2.#

   * Fixed broken __P_ patch in MIT-threads

   * Many memory overrun checks. All string functions now return `NULL'
     if the returned string should be longer than `max_allowed_packet'.

   * Changed the name if the `INTERVAL' type to `ENUM', because
     `INTERVAL' is used in ANSI SQL.

   * In some cases doing a JOIN + GROUP + INTO OUTFILE, the result
     wasn't grouped.

   * LIKE with '_' as last character didn't work. Fixed

   * Added extended ANSI SQL `TRIM()' function.

   * Added `CURTIME()'.

   * Added `ENCRYPT()' function by Zeev Suraski.

   * Fixed better `FOREIGN KEY' syntax skipping. New reserved words:
     `MATCH', `FULL', `PARTIAL'

   * mysqld now allows ip and hostname to the `--bind-address' option.

   * Added "SET OPTION CHARACTER SET cp1251_koi8" to enable conversions
     off data to/from cp1251_koi8.

   * Lots of changes for Win95 port. In theory this version should now
     be easily portable to Win95.

   * Changed the create column syntax off `NOT NULL' to be after the
     `DEFAULT' value as specified in the ANSI SQL standard. This will
     make mysqldump with `NOT NULL' and default values incompatible with
     *MySQL* 3.20.

   * Added a lot of function name alias so one can use the functions
     with ODBC or ANSI SQL92 syntax.

   * Fixed `ALTER TABLE person ALTER COLUMN phone SET DEFAULT NULL'
     syntax.

   * Added CHAR and BIT as a synonyms for CHAR(1)

   * Fixed core dump when updating as user with only select privilege.

   * INSERT ... SELECT ... GROUP BY didn't work in some cases. On got
     'Invalid use of group function'

   * When using LIMIT, SELECT now always uses keys instead of record
     scan.  This will give better performance on SELECT and a WHERE
     that matches many rows.

   * Added Russian error messages.

   * In some cases doing a join + group + INTO OUTFILE, the result
     wasn't grouped.

Changes in release 3.21.11
--------------------------

   * Configure changes.

   * MySQL new works with the new thread library on BSDI 3.0.

   * Added new group functions: BIT_OR() and BIT_AND().

   * Added compatibility functions: CHECK, REFERENCES. CHECK is now a
     reserved word.

   * Added BIT as a synonym for CHAR(1) to get better compatibility.

   * Added option ALL to GRANT for better compatibility. (GRANT is still
     a dummy fuction.

   * Added partly translated dutch messages.

   * Fixed bug in ORDER BY and GROUP BY with NULL columns

   * Added function last_insert_id() to retreive last auto_increment
     value.  This is for clients to ODBC that can't use the
     mysql_insert_id API function, but can be used by any client.

   * Added option '-flush-logs' to mysqladmin.

   * Added command 'status' to mysql.

   * Fixed problem with order/group by because of bug in gcc.

   * Fixed problem with INSERT ... SELECT .. GROUP BY.

Changes in release 3.21.10
--------------------------

   * New mysqlaccess.

   * CREATE supports now all ODBC types and the mSQL `TEXT' type. All
     ODBC 2.5 functions is also supported (added REPAT). This gives
     better portability.

   * Added text types: `TINYTEXT', `TEXT', `MIDDLETEXT' and `LONGTEXT'.
     These are actually blobs, but all searching is done case
     independent.

   * All old `BLOB' fields are now `TEXT' fields.  This only changes
     that all searching on strings are case independent. One have to do
     a ALTER TABLE and change the field to BLOB if one wants to have
     tests done case dependent.

   * Fixed some configure issues.

   * Made the locking code a bit safer. Fixed very unlikely dead lock
     situation.

   * Fixed a couple of bugs in the range optimizer. Now the new range
     benchmark test-select works.

Changes in release 3.21.9
-------------------------

   * Added -enable-unix-socket=pathname arg to configure.

   * Fixed a couple of portable problems with include files.

   * Fixed bug in range calculation that could return empty set when
     searching on multiple key with only one entry (very rare).

   * Most things ported to FSU threads, which should allow *MySQL* to
     run on SCO. *Note SCO::.

Changes in release 3.21.8
-------------------------

   * Works now in Solaris 2.6

   * Added handling of calculation of sum() functions.  One can now use
     for example: SUM(column)/COUNT(column)

   * Added handling of trigometric functions: PI(), ACOS(), ASIN(),
     ATAN(), COS(), SIN() and TAN().

   * New languages: norwegian, norwegian-ny and portuguese.

   * Fixed parameter bug in net_print in procedure.cc.

   * Fixed a cople of memory leaks.

   * Now allow also the old SELECT ... INTO OUTFILE syntax.

   * Fixed bug with group by and select on key with many values.

   * mysql_fetch_lengths() returned sometimes wrong lengths when one
     used mysql_use_result(). This affected at least some cases of
     mysqldump -quick.

   * Allow TIME, DATE and TIMESTAMP as column names.

   * Fixed bug in optimization of WHERE const op field.

   * Fixed problem when sorting on NULL fields.

   * Fixed a couple of 64bit (Alpha) problems

   * Added option -pid-file=# to mysqld

   * Added date formating to from_unixtime(), originally by Zeev
     Suraski.

   * Fixed bug in BETWEEN in range optimizer (Did only test = of the
     first argument).

   * Added machine dependent files for mit-pthreads i386-SCO. There is
     probably more to do to get this to work on SCO 3.5.

Changes in release 3.21.7
-------------------------

   * Changed to Makefile.am to take advantage of automake 1.2.

   * Added the beginnings of a benchmark suite.

   * Added more secure password handling.

   * Added new client function: mysql_errno() to get the error number of
     the error message. This makes error checking in the client much
     easier.  This makes the new server incompatible with the 3.20.#
     server when running without -old-protocol.  The client code is
     backward compatible.  More information can be found in the README
     file!

   * Fixed some problems when using very long, illegal names.

Changes in release 3.21.6
-------------------------

   * Fixed more portability issues (wrong sigwait and sigset define)

   * configure should now be able to detect the last argument to
     accept().

Changes in release 3.21.5
-------------------------

   * Should now work at FreeBSD 3.0 if one used the
     FreeBSD-3.0-libc_r-1.0.diff which can be found at
     http://www.tcx.se/patches.

   * Added new option to mysqld: -O tmp_table_size=#

   * New function from_unixtime(timestamp) which returns a date string
     in YYYY-MM-DD HH:MM:DD format.

   * New function sec_to_time(seconds) which returns a string in
     H:MM:SS format.

   * new function: substring_index(), originally by Zeev Suraski.

Changes in release 3.21.4
-------------------------

   * Should now configure and compile on OSF1 4.0 with the Dec compiler.

   * configure and compile on BSD3.0 works, but due to some bugs in the
     BSDI 3.0 mysqld doesn't work here yet.

   * configure and compiles on FreeBSD 3.0, but I couldn't get
     pthread_create to work.

Changes in release 3.21.3
-------------------------

   * Added reverse check lookup of hostnames to get better security.

   * Fixed some possible buffer overflows if one uses too long
     filenames.

   * mysqld doesn't accept hostnames that starts with digits followed
     by a '.'  because the hostname may look like a IP.

   * Added option -skip-networking to only allow socket connections.
     (This will not work with MIT threads!)

   * Added check of too long table names for alias.

   * Added check if database name is okey.

   * Addded check if too long table names.

   * Removed wrong free() that killed the server on 'create/drop
     database'.

   * Changed the name of some mysqld -O options to better names.

   * Added option '-O join_cache_size=#'.

   * Added option '-O max_join_size=#' to be able to set a limit how big
     queries (in this case big = slow) one should be able to handle
     without specifying 'SQL_OPTION OPTION_BIG_SELECTS=1'.  A # = is
     about 10 examined records. The default is 'unlimited'.

   * When comparing a TIME, DATE, DATETIME or TIMESTAMP column to a
     constant the constant is converted to a time value before
     comparing.  This will make it easier to get ODBC and particularly
     Access97 to work with the above types. It should also make dates
     easier to use and the compares should be quicker than before.

   * Applied patch from Jochen Wiedmann that fixes that query() in
     mysqlperl now can take queries with \0 in it.

   * Store of timestamp with 2 digit year YYMMDD didn't work.

   * Fix that timestamp isn't automaticly updated if set in a update
     clause.

   * Now the automatic timestamp field is the FIRST timestamp field.

   * SELECT * INTO OUTFILE, which didn't correctly if the outfile
     already existed.

   * 'mysql' now shows thread id when starting or doing a reconnect.

   * Changed the default sort buffer size from 2M to 1M.

Changes in release 3.21.2
-------------------------

   * The range optimizer is cooded, but only 85% tested. It can be
     enabled with -new, but it crashes core a lot yet...

   * More portable. Should compile one AIX and alpha-digital.  At least
     the isam library should be relative 64 bit clean.

   * New isamchk which can detect and fix more problems.

   * New options for isamlog.

   * Using new version of automake

   * Many small portability changes (from the AIX and alpha-digital
     port) Better checking of pthread(s) library.

   * czech error messages by snajdr@pvt.net

   * 'mysql' now shows thread id when starting or doing a reconnect.

   * Decresed some buffers to get less problems on system with little
     memory.  Also added more checks to handle 'out of memory' problems

   * mysqladmin: One can now do 'mysqladmin kill 5,6,7,8'

   * When the max connection limit is reached, one extra connection by
     a user with the PROCESS_ACL privilege is granted.

   * Added new mysqld option: -O backlog=#

   * Increased max packet size from 512K to 1024K for client.

   * Almost all of the functions code is now tested in the intern test
     suite.

   * ALTER TABLE now returns warnings from field conversions.

   * Port changed to 3306 (got it reserved from ISI).

   * Added a fix for Visual Fox Base so that any schema name from a
     table specification is automaticly removed.

   * New function ASCII.

   * Removed the between() function. On should use the 'col BETWEEN a
     AND b' syntax instead.

   * MySQL now doesn't anymore have to use a extra temporary table when
     sorting on functions or SUM functions.

   * Fixed bug that one couldn't use 'table_name.field_name' in UPDATE.

   * Fixed SELECT DISTINCT when using 'hidden group'. For example:
     SELECT DISTINCT MOD(some_field,10) FROM test GROUP BY some_field;
     Note: some_field is normally in the select part. ANSI SQL should
     require it.

Changes in release 3.21.0
-------------------------

   * New keywords used: INTERVAL, EXPLAIN, READ, WRITE, BINARY

   * Added ODBC functions CHAR(num,...) and ASCII(string).

   * Removed function BETWEEN(a,b,c). One should use the standard ANSI
     SYNTAX: expr BETWEEN expr AND expr.

   * New operator IN. This uses a binary search to find a match.

   * New command `LOCK TABLES table_name [AS alias] (READ | WRITE), ...'

   * New server option `mysqld --log-update' to get a log suitable for
     incremental updates

   * new command: EXPLAIN SELECT ... to get info about how the optimzier
     will do the join.

   * For easier client code, the client shouldn't anymore use
     `FIELD_TYPE_TINY_BLOB', `FIELD_TYPE_MEDIUM_BLOB',
     `FIELD_TYPE_LONG_BLOB' or `FIELD_TYPE_VAR_STRING' (as previously
     returned by mysql_list_fields).  One should instead only use
     `FIELD_TYPE_BLOB' or `FIELD_TYPE_STRING'.  If one wants exact
     types one should use the command `SHOW FIELDS' .

   * Added varbinary syntax: `0x######' which can be used as a string
     (default) or a number.

   * `FIELD_TYPE_CHAR' is renamed to `FIELD_TYPE_TINY'.

   * Changed all fields to C++ classes.

   * Removed FORM struct.

   * A field with a `DEFAULT' doesn't have to be `NOT NULL' anymore.

   * New field types:
    `INTERVAL'
          A string with only can take a couple of defined values. The
          value is stored as a 1-3 byte number that automaticly is
          mapped to a string.  This is sorted according to string
          positions!

    `SET'
          A string with may have one or many string values separated
          with ','.  The string is stored as a 1,2,3,4 or 8 byte number
          where each bit stands for a specific string.  This is sorted
          according to unsigned bit value if SET.

   * Now all function calculation is done with double or long long.
     This will give one the full 64 bits range with bit functions and
     fix some conversions that previously could give precision losses.
     One should avoid using 'unsigned long long' columns with full 64
     bits range (numbers bigger than 9223372036854775807) because
     calculations is done with signed long long.

   * ORDER BY  will now put NULL fields first. GROUP BY will also work
     with NULL.

   * Full WHERE with expressions.

   * New range optimizer with can resolve ranges when some prefix
     keypart is constant. Example: SELECT * FROM table_name WHERE
     key_part_1="customer" and key_part_2 >= 10 AND key_part_2 <= 10)

Changes in release 3.20.x
=========================

   Changes from 3.20.18 to 3.20.32b are not documented here since the
the 3.21 release bransched here. And the relevant changes are also
documented as changes to the 3.21 version.

Changes in release 3.20.18
--------------------------

   * Added -p# (remove # directories from path) to isamlog.  All files
     are written with a relative path from the database directory Now
     mysqld shouldn't crash on shutdown when using -log-isam.

   * New mysqlperl version. Is now compatible with msqlperl-0.63.

   * New DBD module available in Contrib/

   * Added group function STD() (standard derivation).

   * The mysql server is now by default compiled without debugging
     information.  This will make the demon smaller and faster.

   * Now one usually only have to give -basedir to mysqld. All other
     paths are relative in a normal installation.

   * BLOBs contained sometimes garbage when used with a SELECT on more
     than one table and ORDER BY.

   * Fixed that calculations that are not in GROUP BY works as expected.
     (ANSI SQL extension) Example: SELECT id,id+1 FROM table GROUP BY id

   * The test of using MYSQL_PWD was reversed. Now MYSQL_PWD is enabled
     as default in the default release.

   * Fixed convert bug which got mysqld to core dump with Aritmetic
     error on Sparc-386

   * Added option -unbuffered to mysql. (For new mysqlaccess)

   * When using overlapping (unnecessary keys) and join over many tables
     the optimizer could get confused and return 0 records.

Changes in release 3.20.17
--------------------------

   * One can now use BLOBs columns and the functions IS NULL and IS NOT
     NULL in the WHERE clause.

   * All communication packages and row buffers are now alloced
     dynamicly on demand. The default `max_allowed_packet' is now 65K
     for the server and 512K for the client. This is mainly used to
     catch wrong packets that could trash all memory. The server limit
     may be changed when it is started.

   * Changed stack usage to use less memory.

   * Changed safe_mysqld to check for running demon.

   * The `ELT()' function is renamed to `FIELD()'.  The new `ELT()'
     function returns a value based on a index: `FIELD()' is the invers
     of `ELT()' Example: `ELT(2,"A","B","C")' returns `"B"'.
     `FIELD("B","A","B","C")' returns `2';

   * COUNT(field) where field could have a NULL value now works.

   * A couple of bug fixed in SELECT .. GROUP BY.

   * Fixed memory overrun bug in WHERE with many unoptimizable brace
     levels.

   * Fixed some small bugs in the grant code.

   * If hostname isn't found by get_hostname, only the IP is checked.
     Before one one got 'Access denies'

   * Inserts of timestamps with values didn't always work.

   * INSERT INTO ... SELECT .. WHERE could give the error 'Dupplicated
     field'

   * Added some tests to safe_mysqld to make it 'safer'

   * LIKE was case sensitive in some places and case insensitive in
     other.  Now `LIKE' is always case insensitive.

   * mysql.cc; Allow '#' anywhere on the line.

   * New command 'SET OPTION SQL_SELECT_LIMIT=#'. Se the FAQ for more
     details.

   * New version of the mysqlaccess script

   * Change from_days() and weekday() to also take a full timestamp or
     a datetime as argument. Before they only took a number of type
     YYYYMMDD or YYMMDD.

   * Added new function unix_timestamp(timestamp_column);

Changes in release 3.20.16
--------------------------

   * More changes in MIT threads to get them safer. Fixed also some link
     bugs at least in SUNOS.

   * Changed mysqld to go around a bug in MIT threads. This makes
     multiple small selects 20 times faster. Now lock_test.pl should
     work.

   * Added mysql_FetchHash(handle) to mysqlperl

   * The mysqlbug script is now distributed built to allow for reporting
     bugs that appear during the build with it.

   * Changed libmysql.c to prefer to use getpwuid() insted of cuserid().

   * Fixed bug in select optimizer when using many tables with the same
     column used as key to different tables.

   * mysql.cc; Allow '#' anywhere on the line.

   * Added new latin2 and Russian KOI8 character tables.

   * Added support for a dummy GRANT command satisfy Powerbuilder.

Changes in release 3.20.15
--------------------------

   * Fixed fatal bug 'packets out of order' when using MIT threads.

   * Removed possible loop when thread waits for command from client
     and fcntl() fails. Thanks to Mike Bretz for finding this bug

   * Changed alarm loop in mysqld.cc because shutdown didn't always
     succeed in Linux.

   * Removed use of termbits from mysql.cc  This conflicted with glibc
     2.0

   * Fixed some syntax errors for at least BSD and Linux.

   * Fixed bug when doing a select as superuser without a database.

   * Fixed bug when doing SELECT with group calculation to outfile.

Changes in release 3.20.14
--------------------------

   * If one gives '-p' or -password to mysql without an argument, the
     password will be asked from the tty.

   * Added default password from MYSQL_PWD. (by Elmar Haneke)

   * Added commando 'kill' to mysqladmin to kill a specific mysql
     thread.

   * Sometimes when doing a reconnect on a down connection this
     succeeded first on second try.

   * Fixed adding a auto_increment key with ALTER_TABLE.

   * AVG() gave too small value on some selects with GROUP BY and ORDER
     BY.

   * Added new DATETIME type (by Giovanni Maruzzelli
     <maruzz@matrice.it>)

   * Fixed that define 'DONT_USE_DEFAULT_FIELDS' works

   * Changed to use a thread to handle alarms instead of signals on
     Solaris to avoid race conditions.

   * Fixed default length of signed numbers. (George Harvey
     <georgeh@pinacl.co.uk>)

   * Allow anything for CREATE INDEX.

   * Add prezeros when packing numbers to DATE, TIME and TIMESTAMP.

   * Fixed a bug in OR of multiple tables (Gave empty set).

   * Added many patches to MIT threads. This fixes at least one lookup
     bug.

Changes in release 3.20.13
--------------------------

   * Added ANSI SQL94 DATE and TIME types.

   * Fixed bug in select with and-or levels.

   * Added support for Slovenian characters. The Contrib directory
     contains source and instructions to add other character sets.

   * Fixed bug with limit and order by.

   * Allow order and group on items that isn't in the select list.
     (Thanks to Wim Bonis <bonis@kiss.de> for pointing this out)

   * Allow setting of timestamp values in INSERT.

   * Fixed bug with SELECT ... WHERE ... = NULL.

   * Added changes for glibc 2.0. To get glibc to work one should add
     the gibc-2.0-sigwait-patch before compiling glibc.

   * Fixed bug in alter table when changeing a not null field to allow
     NULLs.

   * Added some ANS92 synonyms as field types to CREATE TABLE.  CREATE
     TABLE now allows FLOAT(4) and FLOAT(8) to mean FLOAT and DOUBLE.

   * new utility program mysqlaccess by Yves.Carlier@rug.ac.be.  This
     program shows the access rights for a specific user and the grant
     rows which determinate this grant.

   * Added WHERE const op field (by bonis@kiss.de)

Changes in release 3.20.11
--------------------------

   * When using SELECT ... INTO OUTFILE all temporary tables are ISAM
     instead of HEAP to allow big dumps.

   * Changed date functions to be 'string functions'. This fixed some
     'funny' side effects when sorting on dates.

   * Extended ALTER TABLE according to SQL92.

   * Some minor compability changes.

   * Added -port and -socket to all utility programs and mysqld.

   * Fixed MIT threads readdir_r(). Now mysqladmin create database and
     drop database should work.

   * Changed MIT threads to use our tempnam. This should fix the 'sort
     aborted' bug.

   * Added sync of records count in sql_update. This fixed slow updates
     on first connection. (Thanks to Vaclav Bittner for the test)

Changes in release 3.20.10
--------------------------

   * New insert type: INSERT INTO ... SELECT ...

   * mediumblob fixed.

   * Fixed bug in ALTER TABLE and BLOBs.

   * SELECT ... INTO OUTFILE now creates the file in the current
     database directory.

   * DROP TABLE can now take a list of tables.

   * Oracle synonym DESCRIBE (DESC)

   * Changes to make_binary_distribution

   * Added some comments about conifgures c++ link test to installation
     instructions.

   * Added -without-perl to configure.

   * Lot's of small portability changes.

Changes in release 3.20.9
-------------------------

   * Alter table didn't copy null bit. This resulted that NULL fields
     where always NULL.

   * CREATE didn't take numbers as DEFAULT.

   * Some compatibility changes for SunOS.

   * Removed config.cache from old distribution.

Changes in release 3.20.8
-------------------------

   * Fixed bug with ALTER TABLE and multi part keys.

Changes in release 3.20.7
-------------------------

   * New commands: ALTER TABLE, SELECT ... INTO OUTFILE and LOAD DATA
     INFILE.

   * New functions: NOW()

   * Added new field: file_priv to mysql/user table.

   * New scripts 'add_file_priv' which add the new field 'file_priv' to
     the user table. This scripts must be executed if one wants to use
     the new SELECT ... INTO and LOAD DATA INFILE...  commands with a
     version of mysql less than 3.20.7.

   * Fixed bug in locking code, with made lock_test.pl test fail.

   * new files NEW and BUGS

   * Changed select_test.c and insert_test.c to include config.h

   * Added command 'status' to mysqladmin for short logging.

   * Increased max keys to 16 and max key parts to 15.

   * Use of sub keys. A key may now be a prefix of a string field.

   * Added option -k for mysqlshow to get key info for table.

   * Added long options to mysqldump.

Changes in release 3.20.6
-------------------------

   * Portable to more systems because of MIT threads. This will
     automatically be used is configure can not find a -lpthreads
     library.

   * GNU style long options to almost all programs. Test with 'program
     -help'.

   * Some shared library support for linux.

   * The FAQ is now in .texi format and is available in .html, .text,
     .ps,

   * Added new sql function RAND([init])

   * Changed sql_lex to handle \0 unquoted, but the client can't send
     the query through the C api, because it takes a str pointer.  one
     have to use mysql_real_query() to send the query.

   * Added API function: mysql_get_client_info

   * mysqld now uses the N_MAX_KEY_LENGTH from nisam.h as the max
     allowed key length.

   * The following now works: "select filter_nr,filter_nr from filter
     order by filter_nr" Before you got the error: "Column: 'filter_nr'
     in order clause is ambiguous"

   * mysql now outputs \0 \t \n and \\ when writing tab separated
     output.  when encountering ascii 0, tab, newline or \. This is to
     allow printing of binary data in a portable format.  To get old
     behavior use -r (or -raw).

   * Added german error messages (60 of 80 error messages translated)

   * Added new api function: mysql_fetch_lengths(MYSQL_RES *) which
     returns a array of of column lengths (of type uint).

   * Fixed bug with IS NULL in where clause.

   * Changed the optimizer a little to get better results when
     searching on a key part.

   * Added select option STRAIGHT_JOIN to tell the optimizer that it
     should join tables in the given order.

   * Added support of comment starting with '-' in mysql.cc (Postgres
     syntax)

   * You can have select_expressions and table columns in a select which
     are not used in the group part. This makes it efficient to
     implement lookups.  The used column should be a constant for each
     group because the value is calculated only calculated once for the
     first found row in a group.
          SELECT id,lookup.text,sum(*) FROM test,lookup
          WHERE test.id=lookup.id group by id;

   * Fixed bug in SUM(function) (Could make core dump)

   * Changed auto_increment according to SQL_SYNTAX: INSERT into table
     (auto_field) values (0) inserted 0, but the SQL_SYNTAX stated it
     should insert a auto_increment value.

   * mysqlshow.c: Added number of records in table. Had to change the
     client code a little to fix this.

   * mysql now allows double " or "" in strings for embedded ' or ".

   * New math functions:  EXP, LOG, SQRT, ROUND, CEILING

Changes in release 3.20.3
-------------------------

   * The configure source now compiles a thread free client library
     `-lmysqlclient'. This is the only library that needs to be linked
     with client applications.  When using the binary releases one have
     to link with `-lmysql -lmysys -ldbug -lstrings' as before.

   * New readline from bash-2.0.

   * LOTS of small changes to configure and makefiles (and related
     source).

   * There should now be possible to compile in another directory using
     vpath. Tested with GNU Make 3.75.

   * safe_mysqld and mysql.server changed to be more compatible between
     the source and the binary releases.

   * LIMIT takes now one or two numerical arguments.  If one argument
     the argument indicates the maximum number of rows in a result. If
     two arguments the first arguments says the offset to the first row
     to return, the second is the maximum number of rows.  With this
     it's easy to do a poor mans next page/previous page www
     application.

   * Changed name of SQL function FIELDS to ELT.  Changed sql function
     INTERVALL() to INTERVAL().

   * Made SHOW COLUMNS a synonym for SHOW FIELDS.  Added compatibility
     syntax FRIEND KEY to create table. This creates in mysql a non
     unique key on the given columns.

   * Added CREATE INDEX and DROP INDEX as compatibility functions. In
     mysql CREATE INDEX only checks if the index exists and gives an
     error if it doesn't exists. DROP INDEX always succeeds.

   * mysqladmin.c: Added client version to version info.

   * Fixed core dump bug in sql_acl (core on new connection).

   * Removed host,user and db tables from database test in the
     distribution.

   * FIELD_TYPE_CHAR can now be signed (-128 - 127) or unsigned (0 -
     255) Before it was always unsigned.

   * Bug fixes in concat(), weekday()

   * Changed a lot of source to get mysqld to be compiled with SUNPRO
     compiler.

   * SQL functions must now have a '(' directly after the function name.
     user '(' is now regarded as an identifier and a '('

Changes in release 3.20.0
-------------------------

   * The source distribution is done with configure and automake: It
     will make porting much easier.  Readline is included in the
     distribution.

   * Separate client compilation: The client code should be very easy
     to compile on system which doesn't have threads.

   * The old perl interface code is automaticly compiled and installed.
     Automatic compiling of DBD will follow when the new DBD code is
     ported.

   * Dynamic language support: mysqld can now be started with Swedish
     or English (default) error messages.

   * new functions: INSERT(),RTRIM(),LTRIM() and FORMAT().

   * mysqldump now works correctly for all field types (even
     auto_increment). The format for 'show fields from table' is changed
     so the 'type' column contains info suitable for 'CREATE TABLE'.
     In previous releases some CREATE TABLE info had to be patched to
     when recreating tables

   * Some parser bugs from 3.19.5 (blob and timestamp) are corrected.
     Timestamp now returns different date info depending of it's create
     length.

   * Changed parser to allow a database name, table name and field name
     to start with a number or '_'.

   * All old C code from UNIREG changed to c++ and cleaned up. This
     makes the demon a little smaller and easier to understand.

   * A lot of small bug fixes done.

   * New INSTALL files (not final version) and some info regarding
     porting.

Changes in release 3.19.x
=========================

Changes in release 3.19.5
-------------------------

   * Some new functions, some more optimization on joins.

   * Should now compile clean on Linux (2.0.x)

   * Added functions DATABASE(),USER(),POW(),LOG10() (needed for ODBC).

   * In a WHERE with a ORDER BY on fields from only one table the table
     is now preferred as first table in a multi-join.

   * HAVING and IS NULL or IS NOT NULL now works.

   * A group on one column and a sort on a group function (SUM,AVG...)
     didn't work together. Fixed.

   * mysqldump: Didn't send password to server.

Changes in release 3.19.4
-------------------------

   * Fixed horrible locking bug when inserting in one thread and reading
     on another thread.

   * Fixed one-off decimal bug.  1.00 was outputed as 1.0

   * Added attribute 'Locked' to process list as info if a query is
     locked by another query.

   * Fixed full magic timestamp. Timestamp length may now be
     14,12,10,8,6,4 or 2.

   * sort on some number functions could be sorted wrong on last number.

   * if(arg,syntax_error,syntax_error) crashed.

   * added functions ceiling() and round(), exp(), log() and sqrt()

   * enchanted BETWEEN to handle strings.

Changes in release 3.19.3
-------------------------

   * Fixed that select with grouping on blob's doesn't return wrong blob
     info. grouping, sorting and distinct on blobs will not yet work as
     expected (Probably it will group/sort by the first 7 characters in
     the blob). Groping on formulas with a fixed string size (use mid
     on blob) should work.

   * When doing a full join (no direct keys) on multiple tables with
     blob fields, the blob was garbage on output.

   * Fixed distinct with calculated columns.

Known errors and design deficiencies in *MySQL*
***********************************************

   * You can not build in another directory when using mit-pthreads.
     Since this requires changes to mit-pthreads we are not likely to
     fix this.

   * HAVING can only use fields in select expression list. Functions
     must be aliased.

   * Blobs can't 'reliably' be used in `GROUP BY' or `ORDER BY' or
     `DISTINCT'. Only the first `max_sort_length' (default 1024) are
     used when comparing blobs in these cases.  This can be changed with
     the `-O max_sort_length' parameter to mysql. A workaround for most
     cases is to use a substring: `SELECT DISTINCT LEFT(blob,2048) FROM
     table'.

   * Calculation is done with `bigint' or `double' (both are normally
     64 bit long). It depends on the function which precision one gets.
     The general rule is that bit functions are done with bigint
     precision, IF, and ELT() with bigint or double precision and the
     rest with double precision.

   * All field types are fixed point fields. That means one must
     specify how many decimals a floating point field shall have. All
     results will be returned with the correct number of decimals.

   * All string columns, except BLOBS, have automatically all end spaces
     removed when retrieved. For CHAR types this is ok may be regarded
     as a feature according to ANSI SQL92. The bug is that VARCHAR
     columns are treated the same way. And a compare with a string
     constat should remove spaces too. For example the following query
     never returns anything if name isn't a BLOB.  `SELECT * FROM table
     WHERE name = 'david ''

   For platform specific bugs see the sections about compiling and
porting.

List of thing we want to add to *MySQL* in the future.
******************************************************

   Everything in this list is in the order it will be done.  If you
want to affect the priority order, please register a licence or support
us and tell us what you want to have done more quickly. *Note Licensing
and Support::.

Things what has to be done in the real near future.
===================================================

   * Benchmarks.

   * WIN95 port

   * FreeBSD and MIT-threads;  Do sleeping threads take CPU?

   * Allow join on key parts (optimizing issue).

   * Check why 'delete' uses 'record check'

   * Fix that BETWEEN recognizes binary strings. Now BETWEEN is case
     insensitive.

   * Fix that temporary HEAP tables is automatically converted to NISAM
     if they get too big. At the moment one gets 'error 135' if one
     does a query which has to use a big temporary table.

   * Add EXTRACT function

   * Subqueries. 'select id from t where grp in (select grp from g
     where u > 100)'

   * Change conv_blob to handle blob as a text field.

   * Entry for DECRYPT() and ENCRYPT();

   * Fix libmysql.c to allow two mysql_query() commands in a row without
     reading results or give a nice error message when one does this.

   * Remember FOREIGN key definitions in the .frm file.

   * Add date formating to now().

   * Add GET_LOCK and RELEASE_LOCK commands to implement application
     level locking. These locks are thought be tagged to a string to
     allow one to use it in a very wide range of applications.  The
     locks would be saved in memory in the server and implemented with
     mutex for high speed.

   * Optimzie BIT type to take 1 bit (now BIT takes 1 char).

   * Check why MIT-threads ctime() doesn't work on some FreeBSD systems.

   * Check if locked threads take any cpu.

   * Add ORDER BY to update. This would be handy with functions like:
     generate_id(start,step).

Things that have to be done sometime.
=====================================

   * Implement a table optimizer by a analyze procedure call that
     returns a table like show fields with min and max value and the
     best *MySQL* type for that expression.

   * get_changed_tables(timeout,table1,table2,...)

   * Change the protocol to add more bits to field information.  For
     example AUTO_INCREMENT.

   * Optimize MIN() and MAX() to use keys for quick return.

   * New function: LAST_UPDATED(table_name)

   * Atomic updates; This includes a language that one can even use for
     stored procedures.

   * Change reading through tables to use memmap when possible. Now only
     compressed tables use memmap.

   * Make a SQL standard GRANT command with *MySQL* extensions.

   * Change CREATE INDEX to use ALTER TABLE or add secondary indexes.

   * Change DROP INDEX to use ALTER TABLE or use secondary indexes.

   * Add a new privilege 'Show_priv' for 'SHOW' commands.

   * Make the automatic timestamp code nicer.  Add timestamps to the
     update log with SET TIMESTAMP=#;

   * Optimize the autoincrement code.

   * Use read/write mutex in some places to get more speed.

   * Full foreign key support. One probably wants to implement a
     procedural language first.

   * Simple views (first on one table, later on any expression).

   * Add DISTINC qualifier to COUNT(), SUM()...

   * When one finds a field=#, change all occurrence of field to #.
     Now this is only done for some simple cases.

   * Change all const expression with calculated expressions if
     possible.

   * Optimize key = expression. At the moment only key = field or key =
     constant are optimized.

   * Join some of the copy functions for nicer code.

   * Change sql_yacc.y to an inline parser to get down it's size and get
     better error messages (5 days)

   * Change the parser to use only one rule per different number of
     arguments in function.

   * Use of full calculation names in the order part. (For ACCESS97)

   * SQL_OPTION MAX_SELECT_TIME=#to put a time limit on a query.

   * Fix sorting and grouping of blobs (partly solved now).

   * Make the update log to a database.

   * Negative LIMIT to retrieve data from the end.

   * Alarm round client connect/read/write functions.

   * Add own hostname-ip memory table for cached reverse name lookup.

   * Make a mysqld version which isn't multithreaded (2-4 days).

   * Please note the changes to safe_mysqld: according to FSSTND (which
     Debian tries to follow) PID files should go into
     /var/run/<progname>.pid and log files into /var/log. It would be
     nice if you could put the "DATADIR" in the first declaration of
     "pidfile" and "log", so the placement of these files can be
     changed with a single statement.

   Time is given according to amount of work, not real time. TcX's main
business is the use of *MySQL* not the development of it. But since TcX
is a very flexible company and we have put a lot of resources into the
development of *MySQL*.

Some things we don't have any plans to do.
==========================================

   * Transactions with rollback (we mainly do selects, and because we
     don't do transactions we can be much quicker on everything else).
     We will support some kind of atomic operations on multiple tables
     though. Currently atomic operations can be done with `LOCK
     TABLES'/`UNLOCK TABLES' but we will make this more automatic in the
     future.

Comments on porting to other systems.
*************************************

   A working Posix thread library is needed for the server. On Solaris
2.5 we use SUN PThreads (the native thread support in 2.4 and earlier
versions are not good enough) and on Linux we use LinuxThreads by Xavier
Leroy <Xavier.Leroy@inria.fr>.

   The hard part of porting to a new UNIX variant without good native
thread support is probably to port MIT threads. See
`mit-pthreads/README' and Programming POSIX Threads (http://www.humanfactor.com/pthreads/).

   The *MySQL* distribution includes a patched version of Provenzano's
Pthreads from MIT (see
MIT Pthreads web page (http://www.mit.edu:8001/people/proven/pthreads.html)). This can be used for some operating systems that does not have
posix threads.

   It is also possible to use another user level thread package named
FSU Pthreads (see
FSU pthread home page (http://www.informatik.hu-berlin.de/~mueller/pthreads.html)). This implementation is being used for the SCO port.

   See the `thr_lock.c' and `thr_alarm.c' programs in the mysys
directory for some tests/examples of these problems

   Both the server and the client needs a working C++ compiler (we use
gcc and have tried SparcWorks). Other compiler that is known to work is
the IRIX cc.

   To compile only the client use `./configure --without-server'

   There currently no support for only compiling the server. Nor is it
likly to be added unless someone has a good reason for it.

   If you want/need to change any Makefile or the configure script you
must get automake and autoconf. We have used autoconf-2.12 and
automake-1.2.

   All steps needed to remake everything from the most basic files.

     /bin/rm */.deps/*.P
     /bin/rm -f config.cache
     aclocal
     autoheader
     aclocal
     automake
     autoconf
     ./configure --with-debug=yes --prefix='your installation directory'
     
     # The makefiles generated above needs GNU make (called gmake below)
     gmake clean all install init-db

Debugging *MySQL*
=================

   If you have some very specific problem, you can always try to debug
MySQL.

   Start the mysql server with a trace log in /tmp/mysql.trace. The log
file will get very *BIG*.

   `mysqld --debug'

   or you can start it with

   `mysqld --debug=d,info,error,query,general,where:O,/tmp/mysql.trace'

   which only prints information with the most interesting tags.

Comments about RTS threads:
===========================

   I have tried to use the RTS thread packages with *MySQL* but
stumbled on the following problems:

   They use old version of a lot of POSIX calls and it is very tedious
to make wrappers for all functions. I am inclined to think that it would
be easier to change the thread libraries to the newest POSIX
specification.

   Some wrappers are already written. Se mysys/my_pthread.c for more
info.

   At least the following should be changed:

   pthread_get_specific should use on argument.  sigwait should take
two arguments.  A lot of functions (at least pthread_cond_wait,
pthread_cond_timedwait) should return the error code on error. Now they
return -1 and set errno.

   Another problem is that user level threads uses the ALRM signal and
this aborts a lot of functions (read, write, open...). *MySQL* should
do a retry on interrupt on all of these but it not that easy to verify
it.

   The biggest unsolved problem is the following:

   To get thread_level alarms I changed mysys/thr_alarm.c to wait
between alarms with pthread_cond_timedwait() but this aborts with error
EINTR.  I tried to debug the thread library why this happens but
couldn't find any easy solution.

   If someone wants to try *MySQL* with RTS threads I suggest the
following:

   * Change functions *MySQL* uses from the thread library to POSIX.
     This shouldn't take that long.

   * Compile all libraries with the -DHAVE_rts_threads.

   * Compile thr_alarm

   * If there is some small differences in the implementation they may
     be fixed by changing my_pthread.h and my_pthread.c

   * Run thr_alarm. If it runs without any 'warning', 'error' or
     aborted messages you are one the right track. Here follows an
     successful run on Solaris:
          Main thread: 1
          Tread 0 (5) started
          Thread: 5  Waiting
          process_alarm
          Tread 1 (6) started
          Thread: 6  Waiting
          process_alarm
          process_alarm
          thread_alarm
          Thread: 6  Sleeped for 1 (1) sec
          Thread: 6  Waiting
          process_alarm
          process_alarm
          thread_alarm
          Thread: 6  Sleeped for 2 (2) sec
          Thread: 6  Simulation of no alarm needed
          Thread: 6  Sleeped for 0 (3) sec
          Thread: 6  Waiting
          process_alarm
          process_alarm
          thread_alarm
          Thread: 6  Sleeped for 4 (4) sec
          Thread: 6  Waiting
          process_alarm
          thread_alarm
          Thread: 5  Sleeped for 10 (10) sec
          Thread: 5  Waiting
          process_alarm
          process_alarm
          thread_alarm
          Thread: 6  Sleeped for 5 (5) sec
          Thread: 6  Waiting
          process_alarm
          process_alarm
          
          ...
          thread_alarm
          Thread: 5  Sleeped for 0 (1) sec
          end

What is the difference between different thread packages?
=========================================================

   *MySQL* is very dependent on the used thread package. So when
choosing a good platform for *MySQL* the thread package is very
important.

   There are at least three types of thread packages.

   * User threads in a single process. Thread switching is managed with
     alarms and the threads library manages all not thread- safe
     functions with locks. Read, write and select are usually managed
     with a thread-specific select that switches to another thread if
     the running threads have to wait for data.  If the user thread
     packages are integrated in the standard libs (FreeBSD and BSDI
     threads) the thread package requires less overhead than thread
     packages that have to map all unsafe calls (MIT-threads,
     FSU-threads and RTS threads).  In some environments (for example
     SCO), all system calls are thread- safe so the mapping can be done
     very easily (FSU-threads on SCO).  Downside: All mapped calls take
     a little time and it's quite tricky to be able to handle all
     situations. There are usually also some system calls that are not
     handled by the thread package (like MIT-threads and sockets).
     Thread scheduling isn't always optimal.

   * User threads in separate processes. Thread switching is done by the
     kernel and all data is shared between threads.  The thread package
     manages the standard thread calls to allow sharing data between
     threads.  Linuxthreads is using this method.  Downside: Lots of
     processes. Thread creating is slow. If one thread dies the rest
     are usually left hanging and one has to kill them all before
     restarting. Thread switching is somewhat expensive.

   * Kernel threads. Thread switching is handled by the thread library
     or the kernel and is very fast. Everything is done in one process
     but 'ps' may on some systems show the different threads. If one
     thread aborts the whole process aborts. Most system calls are
     threadsafe and should require very little overhead.  Solaris,
     HPUX, AIX and OSF1 has kernel threads.

   In some systems kernel threads are managed by integrating user level
threads in the system libraries. In such cases, the thread switching
can only be done by the thread library and the kernel isn't really
'thread aware'.

Description of *MySQL* regular expression syntax.
*************************************************

   Regular expressions are a powerful way of specifying complex
searches.

   *MySQL* uses regular Henry Spencers inplementation of regular
expressions. And that is aimed to conform to POSIX 1003.2. *MySQL* uses
the extended version.

   To get more exact information see Henry Spencers regex.7 manual that
is included in the source distribution. *Note Credits::.

   This is a simplistic reference that skips the details. From here on a
regualr expressions is called a regexp.

   A regular expression describes a set of strings. The simplest case is
one that has no special characters in it. For example the regexp
`hello' matches `hello' and nothing else.

   Nontrivial regular expressions use certain special constructs so that
they can match more than one string. For example, the regexp
`hello|word' matches either the string `hello' or the string `word'.

   And a more comples example regexp `B[an]*s' matches any of the
strings `Bananas', `Baaaaas', `Bs' and all other string starting with a
`B' and continuing with any number of `a' `n' and ending with a `s'.

   The following special characters/constructs are known.
`^'
     Start of whole string.
          mysql> select "fo\nfo" regexp "^fo$";           -> 0
          mysql> select "fofo" regexp "^fo";              -> 1

`$'
     End of whole string.
          mysql> select "fo\no" regexp "^fo\no$";         -> 1
          mysql> select "fo\no" regexp "^fo$";            -> 0

`.'
     Any character (including newline).
          mysql> select "fofo" regexp "^f.*";             -> 1
          mysql> select "fo\nfo" regexp "^f.*";           -> 1

`a*'
     Any sequence of zero or more a's.
          mysql> select "Ban" regexp "^Ba*n";             -> 1
          mysql> select "Baaan" regexp "^Ba*n";           -> 1
          mysql> select "Bn" regexp "^Ba*n";              -> 1

`a+'
     Any sequence of one or more a's.
          mysql> select "Ban" regexp "^Ba+n";             -> 1
          mysql> select "Bn" regexp "^Ba+n";              -> 0

`a?'
     Either zero or one a.
          mysql> select "Bn" regexp "^Ba?n";              -> 1
          mysql> select "Ban" regexp "^Ba?n";             -> 1
          mysql> select "Baan" regexp "^Ba?n";            -> 0

`de|abc'
     Either the sequence `de' or `abc'.
          mysql> select "pi" regexp "pi|apa";             -> 1
          mysql> select "axe" regexp "pi|apa";            -> 0
          mysql> select "apa" regexp "pi|apa";            -> 1
          mysql> select "apa" regexp "^(pi|apa)$";        -> 1
          mysql> select "pi" regexp "^(pi|apa)$";         -> 1
          mysql> select "pix" regexp "^(pi|apa)$";        -> 0

`(abc)*'
     Zero or more times the sequence `abc'.
          mysql> select "pi" regexp "^(pi)+$";            -> 1
          mysql> select "pip" regexp "^(pi)+$";           -> 0
          mysql> select "pipi" regexp "^(pi)+$";          -> 1

`{1}'
`{2,3}'
     The is a more general way of writing regexps that match many
     occurences.
    `a*'
          Can be written as `a{0,}'.

    `+'
          Can be written as `a{1,}'.

    `?'
          Can be written as `a{0,1}'.  To be more precice an atom
     followed by a bound containing one integer `i' and no comma
     matches a sequence of exactly `i' matches of the atom. An atom
     followed by a bound containing one integer `i' and a comma matches
     a sequence of `i' or more matches of the atom.  An atom followed
     by a bound containing two integers `i' and `j' matches a sequence
     of `i' through `j' (inclusive) matches of the atom.

     Both arguments must `0 >= value <= RE_DUP_MAX (default 255)', and
     if there are two of them, the second must be bigger or equal to the
     first.

`[a-dX]'
`[^a-dX]'
     Any character which is (not if ^ is used) either `a', `b', `c',
     `d' or `X'. To include `]' it has to be written first. To include
     `-' it has to be written first or last. So `[0-9]' matches any
     decimal digit. All character that does not have a defined mening
     inside a `[]' pair has no special meaning and macthes only itself.
          mysql> select "aXbc" regexp "[a-dXYZ]";         -> 1
          mysql> select "aXbc" regexp "^[a-dXYZ]$";       -> 0
          mysql> select "aXbc" regexp "^[a-dXYZ]+$";      -> 1
          mysql> select "aXbc" regexp "^[^a-dXYZ]+$";     -> 0
          mysql> select "gheis" regexp "^[^a-dXYZ]+$";    -> 1
          mysql> select "gheisa" regexp "^[^a-dXYZ]+$";   -> 0

`[[.characters.]]'
     The sequence of characters of that collating element. The sequence
     is a single element of the bracket expression's list. A bracket
     expression containing a multi-character collating element can thus
     match more than one character, e.g. if the collating sequence
     includes a `ch' collating element, then the RE `[[.ch.]]*c'
     matches the first five characters of `chchcc'.

`[=character-class=]'
     An equivalence class, standing for the sequences of characters of
     all collating elements equivalent to that one, including itself.

     For example, if `o' and `(+)' are the members of an equivalence
     class, then `[[=o=]]', `[[=(+)=]]', and `[o(+)]' are all
     synonymous. An equivalence class may not be an endpoint of a range.

`[:character_class:]'
     Within a bracket expression, the name of a character class
     enclosed in `[:' and `:]' stands for the list of all characters
     belonging to that class. Standard character class names are:

     alnum                  digit                  punct                  
     alpha                  graph                  space                  
     blank                  lower                  upper                  
     cntrl                  print                  xdigit                 

     These stand for the character classes defined in ctype(3). A
     locale may provide others. A character class may not be used as an
     endpoint of a range.
          mysql> select "justalnums" regexp "[[:alnum:]]+";       -> 1
          mysql> select "!!" regexp "[[:alnum:]]+";               -> 0

`[[:<:]]'
`[[:>:]]'
     These match the null string at the beginning and end of a word
     respectively.  A word is defined as a sequence of word characters
     which is neither preceded nor followed by word characters. A word
     character is an alnum character (as defined by ctype(3)) or an
     underscore.
          mysql> select "a word a" regexp "[[:<:]]word[[:>:]]";      -> 1
          mysql> select "a xword a" regexp "[[:<:]]word[[:>:]]";     -> 0

     mysql> select "weeknights" regexp "^(wee|week)(knights|nights)$"; -> 1

What is UNIREG ?
****************

   Unireg is our tty interface builder, but it uses a low level
connection to our NISAM (with is used by *MySQL*) and because of this
it is very quick. It has existed since 1979 (on Unix in C since ~1986).

   Unireg has the following components:

   * One table viewer with updates/browsing.

   * Multi table viewer (with 1 scrolling region).

   * Table creator. (With lots of column tags you can't create with
     *MySQL*) This is WYSIWYG (for a tty). You design a screen and
     Unireg prompts for the column specification.

   * Report generator.

   * A lot of utilities (Quick export/import of tables to/from text
     files, analysis of table contents...).

   * Powerful multi table updates (which we use a lot) with a BASIC like
     language with LOTS of functions.

   * Dynamic languages (at present in Swedish and Finnish). If somebody
     wants an English version there are a few files that would have to
     be translate.

   * The ability to run updates interactively or in a batch.

   * Emacs like key definitions with keyboard macros.

   * All this in a binary of 800k.

   * The convform utility. Changes .frm and text files between different
     character sets.

   * The pack_isam utility. Packs a NISAM table (makes it 50-80%
     smaller). The table can be read by *MySQL* like an ordinary table.
     Only 1 record has to be decompressed / access. Cannot handle
     BLOB:s or updates (yet).

   We update most of our production databases with the UNIREG interface
and serve web pages through *MySQL* (and in some extreme cases the
UNIREG report generator).

   Unireg takes about 3M of disk space and works on at least the
following platforms: SUN OS 4.x, Solaris, Linux, HPUX, ICL Unix, DNIX,
SCO and MSDOS.

   Unireg is currently only available in Swedish and Finnish.

   The price tag for UNIREG is 10,000 Swedish kr (about 1500$ US), but
this includes support. UNIREG is distributed as a binary. (But all the
ISAM sources can be found in *MySQL*). Usually we compile the binary
for the customer at their site.

   All new development is concentrated to *MySQL*.

The *MySQL* server license
**************************

                      *MySQL FREE PUBLIC LICENSE*

                      (Version 4, March 5, 1995)

    Copyright (C) 1995, 1996 TcX AB & Monty Program KB & Detron HB

       Stockholm SWEDEN, Helsingfors FINLAND and Uppsala SWEDEN

                         All rights reserved.

   NOTE: This license is not the same as any of the GNU Licenses
published by the Free Software Foundation.  Its terms are substantially
different from those of the GNU Licenses.  If you are familiar with the
GNU Licenses, please read this license with extra care.

   This License applies to the computer program known as "*MySQL*".
The "Program", below, refers to such program, and a "work based on the
Program" means either the Program or any derivative work of the Program,
as defined in the United States Copyright Act of 1976, such as a
translation or a modification.  The Program is a copyrighted work whose
copyright is held by TcX Datakonsult AB and Monty Program KB and Detron
HB.

   BY MODIFYING OR DISTRIBUTING THE PROGRAM (OR ANY WORK BASED ON THE
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.  NOTHING OTHER THAN THIS LICENSE GRANTS
YOU PERMISSION TO MODIFY OR DISTRIBUTE THE PROGRAM OR ITS DERIVATIVE
WORKS.  THESE ACTIONS ARE PROHIBITED BY LAW.  IF YOU DO NOT ACCEPT THESE
TERMS AND CONDITIONS, DO NOT MODIFY OR DISTRIBUTE THE PROGRAM.

  1. Licenses.

     Licensor hereby grants you the following rights, provided that you
     comply with all of the restrictions set forth in this License and
     provided, further, that you distribute an unmodified copy of this
     License with the Program:

       a. You may copy and distribute literal (i.e., verbatim) copies
          of the Program's source code as you receive it throughout the
          world, in any medium.

       b. You may modify the Program, create works based on the Program
          and distribute copies of such throughout the world, in any
          medium.

  2. Restrictions.

     This license is subject to the following restrictions:
       a. Distribution of the Program or any work based on the Program
          by a commercial organization to any third party is prohibited
          if any payment is made in connection with such distribution,
          whether directly (as in payment for a copy of the Program) or
          indirectly (as in payment for some service related to the
          Program, or payment for some product or service that includes
          a copy of the Program "without charge"; these are only
          examples, and not an exhaustive enumeration of prohibited
          activities).  However, the following methods of distribution
          involving payment shall not in and of themselves be a
          violation of this restriction:

            A. Posting the Program on a public access information
               storage and retrieval service for which a fee is
               received for retrieving information (such as an on-line
               service), provided that the fee is not content-dependent
               (i.e., the fee would be the same for retrieving the same
               volume of information consisting of random data).

            B. Distributing the Program on a CD-ROM, provided that the
               files containing the Program are reproduced entirely and
               verbatim on such CD-ROM, and provided further that all
               information on such CD-ROM be redistributable for
               non-commercial purposes without charge.

       b. Activities other than copying, distribution and modification
          of the Program are not subject to this License and they are
          outside its scope.  Functional use (running) of the Program
          is not restricted, and any output produced through the use of
          the Program is subject to this license only if its contents
          constitute a work based on the Program (independent of having
          been made by running the Program).

       c. You must meet all of the following conditions with respect to
          the distribution of any work based on the Program:
            A. If you have modified the Program, you must cause your
               work to carry prominent notices stating that you have
               modified the Program's 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
               and 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, at each time
               the modified program commences operation, 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).  Such
               notice must also state that users may redistribute the
               Program only under the conditions of this License and
               tell the user how to view the copy of this License
               included with the Program.  (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.);

            D. You must accompany any such work based on the Program
               with the complete corresponding machine-readable source
               code, delivered on a medium customarily used for
               software interchange.  The source code for a work means
               the preferred form of the work for making modifications
               to it.  For an executable work, 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 executable code.  However, the source code
               distributed need not include anything that is normally
               distributed (in either source or binary form) with the
               major components (compiler, kernel, and so on) of the
               operating system on which the executable runs, unless
               that component itself accompanies the executable code;

            E. If you distribute any written or printed material at all
               with the Program or any work based on the Program, such
               material must include either a written copy of this
               License, or a prominent written indication that the
               Program or the work based on the Program is covered by
               this License and written instructions for printing
               and/or displaying the copy of the License on the
               distribution medium;

            F. You may not impose any further restrictions on the
               recipient's exercise of the rights granted herein.

               If distribution of executable or object code is made by
               offering the equivalent ability to copy from a
               designated place, then offering equivalent ability 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 code along
               with the object code.

  3. Reservation of Rights.

     No rights are granted to the Program except as expressly set forth
     herein.  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.  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.

  4. Other Restrictions.

     If the distribution and/or use of the Program is restricted in
     certain countries for any reason, Licensor may add an explicit
     geographical distribution limitation excluding 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.

  5. Limitations.

     THE PROGRAM IS PROVIDED TO YOU "AS IS," WITHOUT WARRANTY.  THERE
     IS NO WARRANTY FOR THE PROGRAM, EITHER EXPRESSED OR IMPLIED,
     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AND
     NONINFRINGEMENT OF THIRD PARTY RIGHTS.  THE ENTIRE RISK AS 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.

     IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
     WRITING WILL LICENSOR, 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 OUT OF THE USE OR INABILITY TO USE
     THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA
     BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 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.

SQL command, type and function index.
*************************************

* Menu:

* !:                                     Logical functions.
* !=:                                    Comparison functions.
* %:                                     Mathematical functions.
* &:                                     Bit functions.
* &&:                                    Logical functions.
* (:                                     Grouping functions.
* ):                                     Grouping functions.
* *:                                     Arithmetic functions.
* +:                                     Arithmetic functions.
* - <1>:                                 Arithmetic functions.
* -:                                     Mathematical functions.
* /:                                     Arithmetic functions.
* <:                                     Comparison functions.
* <=:                                    Comparison functions.
* <>:                                    Comparison functions.
* =:                                     Comparison functions.
* >:                                     Comparison functions.
* >=:                                    Comparison functions.
* A BETWEEN B AND C:                     Comparison functions.
* ABS():                                 Mathematical functions.
* ACOS(X):                               Mathematical functions.
* ALTER TABLE:                           Create table.
* AND:                                   Logical functions.
* Aritmetic expressions:                 Arithmetic functions.
* ASCII(S):                              String functions.
* ASIN(X):                               Mathematical functions.
* ATAN(X):                               Mathematical functions.
* ATAN2(X,Y):                            Mathematical functions.
* AVG(expr):                             Group by functions.
* BIGINT:                                Column types.
* BIT_AND(expr):                         Group by functions.
* BIT_COUNT():                           Bit functions.
* BIT_OR(expr):                          Group by functions.
* BLOB:                                  Column types.
* BLOB (Generic):                        Type details.
* CEILING():                             Mathematical functions.
* CHAR:                                  Column types.
* CHAR(X,...):                           String functions.
* CHAR_LENGTH(S):                        String functions.
* CHARACTER_LENGTH(S):                   String functions.
* ChopBlanks:                            Perl DBI Class.
* CONCAT(X,Y...):                        String functions.
* connect:                               Perl DBI Class.
* COS(X):                                Mathematical functions.
* COT(N):                                Mathematical functions.
* COUNT(Expr):                           Group by functions.
* CREATE DATABASE:                       Group by functions.
* CREATE INDEX:                          Grant.
* CREATE TABLE:                          Drop database.
* CURDATE():                             Date and time functions.
* CURRENT_DATE():                        Date and time functions.
* CURRENT_TIME():                        Date and time functions.
* CURRENT_TIMESTAMP():                   Date and time functions.
* CURTIME():                             Date and time functions.
* data_sources:                          Perl DBI Class.
* DATABASE():                            Miscellaneous functions.
* DATE:                                  Column types.
* DATE_FORMAT(Date, Format):             Date and time functions.
* DATETIME:                              Column types.
* DECIMAL:                               Column types.
* DEGREES(N):                            Mathematical functions.
* DELETE:                                Delete table.
* DELETE TABLE:                          Alter table.
* DESC:                                  Explain.
* DESCRIBE:                              Explain.
* disconnect:                            Perl DBI Class.
* do:                                    Perl DBI Class.
* DOUBLE PRECISION:                      Column types.
* DROP DATABASE:                         Create database.
* DROP INDEX:                            Create Index.
* ELT(N, A1, A2, A3...):                 String functions.
* ENCRYPT(String[, Salt]):               Miscellaneous functions.
* ENUM <1>:                              Type details.
* ENUM:                                  Column types.
* execute:                               Perl DBI Class.
* EXP(N):                                Mathematical functions.
* EXPLAIN:                               Show.
* expr IN (value,...):                   String comparison functions.
* expr LIKE expr:                        String comparison functions.
* expr NOT IN (value,...):               String comparison functions.
* expr NOT LIKE expr:                    String comparison functions.
* expr NOT REGEXP expr:                  String comparison functions.
* expr REGEXP expr:                      String comparison functions.
* fetchall_arrayref:                     Perl DBI Class.
* fetchrow_array:                        Perl DBI Class.
* fetchrow_arrayref:                     Perl DBI Class.
* fetchrow_hashref:                      Perl DBI Class.
* FIELD(S, S1, S2, S3...):               String functions.
* finish:                                Perl DBI Class.
* FLOAT:                                 Column types.
* FLOAT(4):                              Column types.
* FLOAT(8):                              Column types.
* FLOAT(M,D):                            Column types.
* FLOOR():                               Mathematical functions.
* FORMAT(Nr, Num):                       Miscellaneous functions.
* FROM_DAYS():                           Date and time functions.
* FROM_UNIXTIME(Unix_timestamp):         Date and time functions.
* FROM_UNIXTIME(Unix_timestamp, Format_string): Date and time functions.
* GRANT:                                 Set option.
* IF(A,B,C):                             Control flow functions.
* IFNULL(A,B):                           Control flow functions.
* INSERT:                                Join.
* INSERT(Org, Start, Length, New):       String functions.
* insertid:                              Perl DBI Class.
* INSTR(A,B):                            String functions.
* INT:                                   Column types.
* INTERVAL(N, N1, N2, N3...):            String functions.
* is_blob:                               Perl DBI Class.
* is_key:                                Perl DBI Class.
* is_not_null:                           Perl DBI Class.
* is_num:                                Perl DBI Class.
* is_pri_key:                            Perl DBI Class.
* ISNULL(A):                             Comparison functions.
* JOIN:                                  Select.
* LAST_INSERT_ID():                      Miscellaneous functions.
* LCASE(A):                              String functions.
* LEFT JOIN:                             Select.
* LEFT(str,length):                      String functions.
* length:                                Perl DBI Class.
* LENGTH(S):                             String functions.
* LIKE:                                  String comparison functions.
* LOAD DATA INFILE:                      Replace.
* LOCATE(A,B):                           String functions.
* LOCATE(A,B,C):                         String functions.
* LOCK TABLES:                           Describe.
* LOG(X):                                Mathematical functions.
* LOG10(X):                              Mathematical functions.
* LONGBLOB:                              Column types.
* LONGTEXT:                              Column types.
* LOWER(A):                              String functions.
* LTRIM(str):                            String functions.
* MAX(expr):                             Group by functions.
* MAX(X,Y...):                           Mathematical functions.
* max_length:                            Perl DBI Class.
* MEDIUMBLOB:                            Column types.
* MEDIUMINT:                             Column types.
* MEDIUMTEXT:                            Column types.
* MID(A, B, C):                          String functions.
* MIN(expr):                             Group by functions.
* MIN(X,Y...):                           Mathematical functions.
* MOD():                                 Mathematical functions.
* mysql_affected_rows:                   C API.
* mysql_close:                           C API.
* mysql_connect:                         C API.
* mysql_create_db:                       C API.
* mysql_data_seek:                       C API.
* mysql_drop_db:                         C API.
* mysql_eof:                             C API.
* mysql_error:                           C API.
* mysql_fetch_field:                     C API.
* mysql_fetch_lengths:                   C API.
* mysql_fetch_row:                       C API.
* mysql_field_seek:                      C API.
* mysql_free_result:                     C API.
* mysql_get_client_info:                 C API.
* mysql_get_host_info:                   C API.
* mysql_get_proto_info:                  C API.
* mysql_get_server_info:                 C API.
* mysql_insert_id:                       C API.
* mysql_list_dbs:                        C API.
* mysql_list_fields:                     C API.
* mysql_list_processes:                  C API.
* mysql_list_tables:                     C API.
* mysql_num_fields:                      C API.
* mysql_num_rows:                        C API.
* mysql_query:                           C API.
* mysql_real_query:                      C API.
* mysql_reload:                          C API.
* mysql_select_db:                       C API.
* mysql_shutdown:                        C API.
* mysql_stat:                            C API.
* mysql_store_result:                    C API.
* mysql_use_result:                      C API.
* NAME:                                  Perl DBI Class.
* NOT:                                   Logical functions.
* NOW():                                 Date and time functions.
* NULLABLE:                              Perl DBI Class.
* NUM_OF_FIELDS:                         Perl DBI Class.
* NUMERIC:                               Column types.
* OCTET_LENGTH(S):                       String functions.
* OR:                                    Logical functions.
* Parenthesis:                           Grouping functions.
* PASSWORD(String):                      Miscellaneous functions.
* PERIOD_ADD(P, N):                      Date and time functions.
* PERIOD_DIFF(A, B):                     Date and time functions.
* PI():                                  Mathematical functions.
* POSITION(B IN A):                      String functions.
* POW(X,Y):                              Mathematical functions.
* POWER(X,Y):                            Mathematical functions.
* prepare:                               Perl DBI Class.
* quote:                                 Perl DBI Class.
* RADIANS(N):                            Mathematical functions.
* RAND([X]):                             Mathematical functions.
* REAL:                                  Column types.
* REPEAT(String, Count):                 String functions.
* REPLACE:                               Insert.
* REPLACE(A, B, C):                      String functions.
* REVERSE(String):                       String functions.
* RIGHT(A,B):                            String functions.
* ROUND(N):                              Mathematical functions.
* ROUND(Number,Decimals):                Mathematical functions.
* rows:                                  Perl DBI Class.
* RTRIM(str):                            String functions.
* SEC_TO_TIME(Seconds):                  Date and time functions.
* SELECT:                                Delete.
* SESSION_USER():                        Miscellaneous functions.
* SET <1>:                               Column types.
* SET:                                   Type details.
* SET OPTION:                            Lock tables.
* SHOW COLUMNS:                          Update.
* SHOW DATABASES:                        Update.
* SHOW FIELDS:                           Update.
* SHOW INDEXES:                          Update.
* SHOW KEYS:                             Update.
* SHOW TABLES:                           Update.
* SIGN():                                Mathematical functions.
* SIN(X):                                Mathematical functions.
* SMALLINT:                              Column types.
* SOUNDEX(S):                            String functions.
* SPACE(N):                              String functions.
* sqrt(X):                               Mathematical functions.
* STD(expr):                             Group by functions.
* STRCMP():                              String comparison functions.
* SUBSTRING(A FROM B FOR C):             String functions.
* SUBSTRING(A FROM B):                   String functions.
* SUBSTRING(A, B, C):                    String functions.
* SUBSTRING_INDEX(String, Delimiter, Count): String functions.
* SUM(expr):                             Group by functions.
* SYSDATE():                             Date and time functions.
* SYSTEM_USER():                         Miscellaneous functions.
* table:                                 Perl DBI Class.
* TAN(X):                                Mathematical functions.
* TEXT:                                  Column types.
* TEXT (Generic):                        Type details.
* TIME:                                  Column types.
* TIME_TO_SEC(Time):                     Date and time functions.
* TIMESTAMP <1>:                         Type details.
* TIMESTAMP:                             Column types.
* TINYBLOB:                              Column types.
* TINYINT:                               Column types.
* TINYTEXT:                              Column types.
* TO_DAYS(Date):                         Date and time functions.
* TRIM([[ BOTH | LEADING | TRAILING] [ A ] FROM ] B): String functions.
* TRUNCATE(Number, Decimals):            Mathematical functions.
* Types:                                 Column types.
* UCASE(A):                              String functions.
* UNIX_TIMESTAMP([Date]):                Date and time functions.
* UNLOCK TABLES:                         Describe.
* UPDATE:                                Load.
* UPPER(A):                              String functions.
* USER():                                Miscellaneous functions.
* VARCHAR:                               Column types.
* VERSION:                               Miscellaneous functions.
* WEEKDAY(Date):                         Date and time functions.
* |:                                     Bit functions.
* ||:                                    Logical functions.

Concept Index
*************

* Menu:

* *MySQL*:                               Manual-info.
* *MySQL* binary:                        Getting it.
* *MySQL* mailing lists:                 SQL-Words.
* *MySQL* mailing lists, un/subscribing to: SQL-Words.
* *MySQL* source:                        Getting it.
* *MySQL* version <1>:                   Installing.
* *MySQL* version:                       What-is.
* Aritmetic functions:                   Arithmetic functions.
* Backup:                                Replication.
* Big5 Chinese character encoding:       Using DATE.
* Bug reports:                           Asking questions.
* Case sensitivity:                      Using DATE.
* Casts:                                 Logical functions.
* Chinese:                               Using DATE.
* Choosing types:                        Type details.
* Choosing version:                      Getting it.
* Client libraries:                      Install-binary.
* Copyright:                             Contacting us.
* Cost:                                  Licensing and Support.
* Disk full:                             Full table.
* Downloading:                           Installing.
* Environment variables.:                Tools.
* Full disk:                             Full table.
* Functions for select & where:          Indexes.
* General Information:                   Top.
* Getting *MySQL*:                       Installing.
* Grouping of expressions:               Functions.
* How to pronounce *MySQL*:              What-is.
* Indexes:                               Choosing types.
* Keys:                                  Choosing types.
* Linking:                               Install-binary.
* Manual information:                    Introduction.
* Net etiquette <1>:                     Crashing.
* Net etiquette:                         Mailing-list.
* ODBC:                                  Adding functions.
* Overview:                              Top.
* Pack-ISAM:                             Low-level-table-info.
* Paying:                                Support.
* Protocol mismatch:                     Upgrading-from-3.20.
* Quoting of binary data:                Base Syntax.
* Release numbers:                       Getting it.
* Replication:                           Common problems.
* Reporting errors:                      SQL-Words.
* Reserved words:                        Drop Index.
* Size of tables:                        Update log.
* Strings, How to escape things:         Syntax.
* Support:                               Cost.
* Table size:                            Update log.
* The table is full:                     Packet to large.
* Type conversions:                      Logical functions.
* Type portability:                      Indexes.
* Types, Choosing:                       Type details.
* Version, Choosing:                     Getting it.
* Version, Latest:                       Installing.
* Windows:                               Adding functions.

